sequel 4.47.0 → 4.48.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 +134 -0
- data/Rakefile +1 -1
- data/doc/release_notes/4.48.0.txt +293 -0
- data/lib/sequel/adapters/ado/access.rb +2 -1
- data/lib/sequel/adapters/do/postgres.rb +5 -2
- data/lib/sequel/adapters/ibmdb.rb +24 -7
- data/lib/sequel/adapters/jdbc.rb +36 -22
- data/lib/sequel/adapters/jdbc/db2.rb +12 -3
- data/lib/sequel/adapters/jdbc/derby.rb +4 -5
- data/lib/sequel/adapters/jdbc/oracle.rb +16 -2
- data/lib/sequel/adapters/jdbc/postgresql.rb +43 -18
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +9 -7
- data/lib/sequel/adapters/jdbc/sqlserver.rb +11 -4
- data/lib/sequel/adapters/mock.rb +24 -19
- data/lib/sequel/adapters/mysql.rb +17 -16
- data/lib/sequel/adapters/mysql2.rb +4 -5
- data/lib/sequel/adapters/oracle.rb +5 -9
- data/lib/sequel/adapters/postgres.rb +89 -102
- data/lib/sequel/adapters/shared/db2.rb +22 -6
- data/lib/sequel/adapters/shared/mssql.rb +5 -4
- data/lib/sequel/adapters/shared/mysql.rb +75 -24
- data/lib/sequel/adapters/shared/postgres.rb +196 -94
- data/lib/sequel/adapters/shared/sqlanywhere.rb +23 -10
- data/lib/sequel/adapters/shared/sqlite.rb +72 -82
- data/lib/sequel/adapters/sqlanywhere.rb +4 -1
- data/lib/sequel/adapters/sqlite.rb +5 -3
- data/lib/sequel/adapters/swift/postgres.rb +5 -2
- data/lib/sequel/adapters/tinytds.rb +0 -5
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -1
- data/lib/sequel/adapters/utils/pg_types.rb +2 -76
- data/lib/sequel/core.rb +2 -2
- data/lib/sequel/database/connecting.rb +5 -5
- data/lib/sequel/database/dataset.rb +6 -3
- data/lib/sequel/database/misc.rb +1 -1
- data/lib/sequel/database/query.rb +3 -0
- data/lib/sequel/database/schema_methods.rb +1 -1
- data/lib/sequel/dataset/actions.rb +18 -10
- data/lib/sequel/dataset/graph.rb +1 -1
- data/lib/sequel/dataset/misc.rb +1 -0
- data/lib/sequel/dataset/prepared_statements.rb +3 -3
- data/lib/sequel/dataset/query.rb +19 -8
- data/lib/sequel/extensions/core_extensions.rb +4 -1
- data/lib/sequel/extensions/duplicate_columns_handler.rb +1 -1
- data/lib/sequel/extensions/empty_array_ignore_nulls.rb +3 -0
- data/lib/sequel/extensions/filter_having.rb +2 -0
- data/lib/sequel/extensions/freeze_datasets.rb +2 -0
- data/lib/sequel/extensions/from_block.rb +1 -1
- data/lib/sequel/extensions/graph_each.rb +2 -2
- data/lib/sequel/extensions/hash_aliases.rb +2 -0
- data/lib/sequel/extensions/identifier_mangling.rb +0 -7
- data/lib/sequel/extensions/meta_def.rb +2 -0
- data/lib/sequel/extensions/migration.rb +6 -6
- data/lib/sequel/extensions/no_auto_literal_strings.rb +1 -1
- data/lib/sequel/extensions/pagination.rb +1 -1
- data/lib/sequel/extensions/pg_array.rb +207 -130
- data/lib/sequel/extensions/pg_hstore.rb +38 -20
- data/lib/sequel/extensions/pg_inet.rb +18 -6
- data/lib/sequel/extensions/pg_interval.rb +19 -12
- data/lib/sequel/extensions/pg_json.rb +25 -14
- data/lib/sequel/extensions/pg_json_ops.rb +2 -2
- data/lib/sequel/extensions/pg_range.rb +133 -100
- data/lib/sequel/extensions/pg_range_ops.rb +4 -3
- data/lib/sequel/extensions/pg_row.rb +68 -39
- data/lib/sequel/extensions/pg_row_ops.rb +11 -5
- data/lib/sequel/extensions/query_literals.rb +2 -0
- data/lib/sequel/extensions/ruby18_symbol_extensions.rb +2 -0
- data/lib/sequel/extensions/s.rb +1 -1
- data/lib/sequel/extensions/schema_dumper.rb +24 -24
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +3 -1
- data/lib/sequel/extensions/sequel_4_dataset_methods.rb +83 -0
- data/lib/sequel/extensions/set_overrides.rb +2 -2
- data/lib/sequel/extensions/string_agg.rb +0 -1
- data/lib/sequel/extensions/symbol_aref.rb +0 -4
- data/lib/sequel/model.rb +25 -57
- data/lib/sequel/model/associations.rb +14 -5
- data/lib/sequel/model/base.rb +96 -32
- data/lib/sequel/plugins/association_pks.rb +73 -46
- data/lib/sequel/plugins/association_proxies.rb +1 -1
- data/lib/sequel/plugins/auto_validations.rb +6 -2
- data/lib/sequel/plugins/boolean_readers.rb +1 -1
- data/lib/sequel/plugins/caching.rb +19 -13
- data/lib/sequel/plugins/class_table_inheritance.rb +19 -10
- data/lib/sequel/plugins/column_conflicts.rb +7 -2
- data/lib/sequel/plugins/column_select.rb +1 -1
- data/lib/sequel/plugins/csv_serializer.rb +8 -8
- data/lib/sequel/plugins/defaults_setter.rb +10 -0
- data/lib/sequel/plugins/eager_each.rb +1 -1
- data/lib/sequel/plugins/force_encoding.rb +2 -2
- data/lib/sequel/plugins/hook_class_methods.rb +9 -12
- data/lib/sequel/plugins/identifier_columns.rb +2 -0
- data/lib/sequel/plugins/instance_filters.rb +3 -1
- data/lib/sequel/plugins/instance_hooks.rb +17 -9
- data/lib/sequel/plugins/json_serializer.rb +17 -10
- data/lib/sequel/plugins/lazy_attributes.rb +8 -7
- data/lib/sequel/plugins/modification_detection.rb +3 -0
- data/lib/sequel/plugins/nested_attributes.rb +5 -1
- data/lib/sequel/plugins/pg_array_associations.rb +5 -0
- data/lib/sequel/plugins/prepared_statements.rb +1 -0
- data/lib/sequel/plugins/rcte_tree.rb +4 -4
- data/lib/sequel/plugins/serialization.rb +3 -10
- data/lib/sequel/plugins/single_table_inheritance.rb +2 -2
- data/lib/sequel/plugins/split_values.rb +6 -5
- data/lib/sequel/plugins/static_cache.rb +31 -25
- data/lib/sequel/plugins/subset_conditions.rb +3 -1
- data/lib/sequel/plugins/table_select.rb +1 -1
- data/lib/sequel/plugins/touch.rb +2 -1
- data/lib/sequel/plugins/validation_class_methods.rb +5 -6
- data/lib/sequel/plugins/validation_helpers.rb +2 -4
- data/lib/sequel/plugins/xml_serializer.rb +4 -4
- data/lib/sequel/sql.rb +2 -2
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +115 -14
- data/spec/adapters/mysql_spec.rb +78 -28
- data/spec/adapters/oracle_spec.rb +24 -24
- data/spec/adapters/postgres_spec.rb +38 -24
- data/spec/adapters/sqlanywhere_spec.rb +88 -86
- data/spec/adapters/sqlite_spec.rb +29 -24
- data/spec/core/connection_pool_spec.rb +17 -0
- data/spec/core/database_spec.rb +6 -0
- data/spec/core/dataset_spec.rb +46 -36
- data/spec/core/schema_spec.rb +16 -0
- data/spec/core/spec_helper.rb +1 -0
- data/spec/core_extensions_spec.rb +6 -2
- data/spec/extensions/active_model_spec.rb +1 -1
- data/spec/extensions/arbitrary_servers_spec.rb +1 -1
- data/spec/extensions/association_pks_spec.rb +34 -2
- data/spec/extensions/auto_literal_strings_spec.rb +5 -1
- data/spec/extensions/auto_validations_spec.rb +2 -0
- data/spec/extensions/boolean_readers_spec.rb +1 -1
- data/spec/extensions/boolean_subsets_spec.rb +1 -1
- data/spec/extensions/class_table_inheritance_spec.rb +48 -2
- data/spec/extensions/column_conflicts_spec.rb +11 -0
- data/spec/extensions/connection_validator_spec.rb +1 -1
- data/spec/extensions/dataset_associations_spec.rb +8 -8
- data/spec/extensions/defaults_setter_spec.rb +1 -1
- data/spec/extensions/filter_having_spec.rb +5 -3
- data/spec/extensions/hash_aliases_spec.rb +3 -1
- data/spec/extensions/identifier_columns_spec.rb +3 -1
- data/spec/extensions/implicit_subquery_spec.rb +4 -2
- data/spec/extensions/json_serializer_spec.rb +18 -0
- data/spec/extensions/lazy_attributes_spec.rb +3 -3
- data/spec/extensions/meta_def_spec.rb +9 -0
- data/spec/extensions/migration_spec.rb +3 -3
- data/spec/extensions/nested_attributes_spec.rb +14 -3
- data/spec/extensions/no_auto_literal_strings_spec.rb +8 -4
- data/spec/extensions/pg_array_associations_spec.rb +29 -18
- data/spec/extensions/pg_array_spec.rb +44 -25
- data/spec/extensions/pg_hstore_spec.rb +10 -0
- data/spec/extensions/pg_inet_spec.rb +26 -0
- data/spec/extensions/pg_interval_spec.rb +20 -0
- data/spec/extensions/pg_json_spec.rb +24 -0
- data/spec/extensions/pg_range_spec.rb +98 -14
- data/spec/extensions/pg_row_spec.rb +14 -4
- data/spec/extensions/prepared_statements_safe_spec.rb +1 -1
- data/spec/extensions/query_literals_spec.rb +3 -1
- data/spec/extensions/schema_dumper_spec.rb +96 -98
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +10 -6
- data/spec/extensions/sequel_4_dataset_methods_spec.rb +121 -0
- data/spec/extensions/single_table_inheritance_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +7 -1
- data/spec/extensions/static_cache_spec.rb +75 -24
- data/spec/extensions/string_agg_spec.rb +1 -1
- data/spec/extensions/touch_spec.rb +9 -0
- data/spec/extensions/validation_helpers_spec.rb +9 -3
- data/spec/extensions/whitelist_security_spec.rb +26 -0
- data/spec/integration/dataset_test.rb +45 -44
- data/spec/integration/plugin_test.rb +20 -0
- data/spec/integration/prepared_statement_test.rb +3 -0
- data/spec/integration/schema_test.rb +21 -1
- data/spec/integration/transaction_test.rb +40 -40
- data/spec/model/class_dataset_methods_spec.rb +14 -4
- data/spec/model/dataset_methods_spec.rb +12 -3
- data/spec/model/model_spec.rb +8 -0
- metadata +6 -4
- data/spec/adapters/firebird_spec.rb +0 -405
- data/spec/adapters/informix_spec.rb +0 -100
|
@@ -28,7 +28,8 @@ module Sequel
|
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
# SEQUEL5: Remove
|
|
32
|
+
class Type_Convertor
|
|
32
33
|
def SqlAnywhereBoolean(r, i)
|
|
33
34
|
if v = Short(r, i)
|
|
34
35
|
v != 0
|
|
@@ -37,6 +38,11 @@ module Sequel
|
|
|
37
38
|
end
|
|
38
39
|
|
|
39
40
|
module SqlAnywhere
|
|
41
|
+
def self.SqlAnywhereBoolean(r, i)
|
|
42
|
+
v = r.getShort(i)
|
|
43
|
+
v != 0 unless r.wasNull
|
|
44
|
+
end
|
|
45
|
+
|
|
40
46
|
# Database instance methods for Sybase databases accessed via JDBC.
|
|
41
47
|
module DatabaseMethods
|
|
42
48
|
include Sequel::SqlAnywhere::DatabaseMethods
|
|
@@ -56,11 +62,6 @@ module Sequel
|
|
|
56
62
|
rs.getLong(1)
|
|
57
63
|
end
|
|
58
64
|
end
|
|
59
|
-
|
|
60
|
-
def setup_type_convertor_map
|
|
61
|
-
super
|
|
62
|
-
@type_convertor_map[:SqlAnywhereBoolean] = TypeConvertor::INSTANCE.method(:SqlAnywhereBoolean)
|
|
63
|
-
end
|
|
64
65
|
end
|
|
65
66
|
|
|
66
67
|
#Dataset class for Sybase datasets accessed via JDBC.
|
|
@@ -70,10 +71,11 @@ module Sequel
|
|
|
70
71
|
private
|
|
71
72
|
|
|
72
73
|
SMALLINT_TYPE = Java::JavaSQL::Types::SMALLINT
|
|
74
|
+
BOOLEAN_METHOD = SqlAnywhere.method(:SqlAnywhereBoolean)
|
|
73
75
|
|
|
74
76
|
def type_convertor(map, meta, type, i)
|
|
75
77
|
if convert_smallint_to_bool && type == SMALLINT_TYPE
|
|
76
|
-
|
|
78
|
+
BOOLEAN_METHOD
|
|
77
79
|
else
|
|
78
80
|
super
|
|
79
81
|
end
|
|
@@ -14,10 +14,9 @@ module Sequel
|
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
# SEQUEL5: Remove
|
|
18
|
+
class Type_Convertor
|
|
18
19
|
def MSSQLRubyTime(r, i)
|
|
19
|
-
# MSSQL-Server TIME should be fetched as string to keep the precision intact, see:
|
|
20
|
-
# https://docs.microsoft.com/en-us/sql/t-sql/data-types/time-transact-sql#a-namebackwardcompatibilityfordownlevelclientsa-backward-compatibility-for-down-level-clients
|
|
21
20
|
if v = r.getString(i)
|
|
22
21
|
Sequel.string_to_time("#{v}")
|
|
23
22
|
end
|
|
@@ -27,6 +26,14 @@ module Sequel
|
|
|
27
26
|
# Database and Dataset instance methods for SQLServer specific
|
|
28
27
|
# support via JDBC.
|
|
29
28
|
module SQLServer
|
|
29
|
+
def self.MSSQLRubyTime(r, i)
|
|
30
|
+
# MSSQL-Server TIME should be fetched as string to keep the precision intact, see:
|
|
31
|
+
# https://docs.microsoft.com/en-us/sql/t-sql/data-types/time-transact-sql#a-namebackwardcompatibilityfordownlevelclientsa-backward-compatibility-for-down-level-clients
|
|
32
|
+
if v = r.getString(i)
|
|
33
|
+
Sequel.string_to_time("#{v}")
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
30
37
|
# Database instance methods for SQLServer databases accessed via JDBC.
|
|
31
38
|
module DatabaseMethods
|
|
32
39
|
include Sequel::JDBC::MSSQL::DatabaseMethods
|
|
@@ -34,7 +41,7 @@ module Sequel
|
|
|
34
41
|
def setup_type_convertor_map
|
|
35
42
|
super
|
|
36
43
|
map = @type_convertor_map
|
|
37
|
-
map[Java::JavaSQL::Types::TIME] =
|
|
44
|
+
map[Java::JavaSQL::Types::TIME] = SQLServer.method(:MSSQLRubyTime)
|
|
38
45
|
if defined?(Java::MicrosoftSql::Types::DATETIMEOFFSET)
|
|
39
46
|
map[Java::MicrosoftSql::Types::DATETIMEOFFSET] = lambda do |r, i|
|
|
40
47
|
if v = r.getDateTimeOffset(i)
|
data/lib/sequel/adapters/mock.rb
CHANGED
|
@@ -52,7 +52,7 @@ module Sequel
|
|
|
52
52
|
@autoid = case v
|
|
53
53
|
when Integer
|
|
54
54
|
i = v - 1
|
|
55
|
-
proc{
|
|
55
|
+
proc{@mutex.synchronize{i+=1}}
|
|
56
56
|
else
|
|
57
57
|
v
|
|
58
58
|
end
|
|
@@ -128,9 +128,11 @@ module Sequel
|
|
|
128
128
|
# Return all stored SQL queries, and clear the cache
|
|
129
129
|
# of SQL queries.
|
|
130
130
|
def sqls
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
131
|
+
@mutex.synchronize do
|
|
132
|
+
s = @sqls.dup
|
|
133
|
+
@sqls.clear
|
|
134
|
+
s
|
|
135
|
+
end
|
|
134
136
|
end
|
|
135
137
|
|
|
136
138
|
# Enable use of savepoints.
|
|
@@ -140,21 +142,12 @@ module Sequel
|
|
|
140
142
|
|
|
141
143
|
private
|
|
142
144
|
|
|
143
|
-
def _autoid(sql, v, ds=nil)
|
|
144
|
-
if ds
|
|
145
|
-
ds.send(:cache_set, :_autoid, ds.autoid + 1) if ds.autoid.is_a?(Integer)
|
|
146
|
-
v
|
|
147
|
-
else
|
|
148
|
-
_nextres(v, sql, nil)
|
|
149
|
-
end
|
|
150
|
-
end
|
|
151
|
-
|
|
152
145
|
def _execute(c, sql, opts=OPTS, &block)
|
|
153
146
|
sql += " -- args: #{opts[:arguments].inspect}" if opts[:arguments]
|
|
154
147
|
sql += " -- #{@opts[:append]}" if @opts[:append]
|
|
155
148
|
sql += " -- #{c.server.is_a?(Symbol) ? c.server : c.server.inspect}" if c.server != :default
|
|
156
149
|
log_connection_yield(sql, c){} unless opts[:log] == false
|
|
157
|
-
@sqls << sql
|
|
150
|
+
@mutex.synchronize{@sqls << sql}
|
|
158
151
|
|
|
159
152
|
ds = opts[:dataset]
|
|
160
153
|
begin
|
|
@@ -165,8 +158,15 @@ module Sequel
|
|
|
165
158
|
if meth == :numrows
|
|
166
159
|
_numrows(sql, (ds.numrows if ds) || @numrows)
|
|
167
160
|
else
|
|
168
|
-
|
|
169
|
-
|
|
161
|
+
if ds
|
|
162
|
+
@mutex.synchronize do
|
|
163
|
+
v = ds.autoid
|
|
164
|
+
if v.is_a?(Integer)
|
|
165
|
+
ds.send(:cache_set, :_autoid, v + 1)
|
|
166
|
+
end
|
|
167
|
+
v
|
|
168
|
+
end
|
|
169
|
+
end || _nextres(@autoid, sql, nil)
|
|
170
170
|
end
|
|
171
171
|
end
|
|
172
172
|
rescue => e
|
|
@@ -182,7 +182,7 @@ module Sequel
|
|
|
182
182
|
if f.all?{|h| h.is_a?(Hash)}
|
|
183
183
|
f.each{|h| yield h.dup}
|
|
184
184
|
else
|
|
185
|
-
_fetch(sql, f.shift, &block)
|
|
185
|
+
_fetch(sql, @mutex.synchronize{f.shift}, &block)
|
|
186
186
|
end
|
|
187
187
|
when Proc
|
|
188
188
|
h = f.call(sql)
|
|
@@ -209,7 +209,7 @@ module Sequel
|
|
|
209
209
|
when Integer
|
|
210
210
|
v
|
|
211
211
|
when Array
|
|
212
|
-
v.empty? ? default : _nextres(v.shift, sql, default)
|
|
212
|
+
v.empty? ? default : _nextres(@mutex.synchronize{v.shift}, sql, default)
|
|
213
213
|
when Proc
|
|
214
214
|
v.call(sql)
|
|
215
215
|
when Class
|
|
@@ -239,6 +239,7 @@ module Sequel
|
|
|
239
239
|
# :sqls :: The array to store the SQL queries in.
|
|
240
240
|
def adapter_initialize
|
|
241
241
|
opts = @opts
|
|
242
|
+
@mutex = Mutex.new
|
|
242
243
|
@sqls = opts[:sqls] || []
|
|
243
244
|
@shared_adapter = false
|
|
244
245
|
|
|
@@ -284,7 +285,7 @@ module Sequel
|
|
|
284
285
|
if cs.all?{|c| c.is_a?(Symbol)}
|
|
285
286
|
ds.columns(*cs)
|
|
286
287
|
else
|
|
287
|
-
columns(ds, sql, cs.shift)
|
|
288
|
+
columns(ds, sql, @mutex.synchronize{cs.shift})
|
|
288
289
|
end
|
|
289
290
|
end
|
|
290
291
|
when Proc
|
|
@@ -394,6 +395,10 @@ module Sequel
|
|
|
394
395
|
def execute_insert(sql, opts=OPTS, &block)
|
|
395
396
|
super(sql, opts.merge(:dataset=>self), &block)
|
|
396
397
|
end
|
|
398
|
+
|
|
399
|
+
def non_sql_option?(key)
|
|
400
|
+
super || key == :fetch || key == :numrows || key == :autoid
|
|
401
|
+
end
|
|
397
402
|
end
|
|
398
403
|
end
|
|
399
404
|
end
|
|
@@ -16,7 +16,7 @@ module Sequel
|
|
|
16
16
|
def boolean(s) s.to_i != 0 end
|
|
17
17
|
def integer(s) s.to_i end
|
|
18
18
|
def float(s) s.to_f end
|
|
19
|
-
end.new
|
|
19
|
+
end.new#.freeze # SEQUEL5
|
|
20
20
|
|
|
21
21
|
# Hash with integer keys and callable values for converting MySQL types.
|
|
22
22
|
MYSQL_TYPES = {}
|
|
@@ -30,14 +30,18 @@ module Sequel
|
|
|
30
30
|
end
|
|
31
31
|
# MYSQL_TYPES.freeze # SEQUEL5
|
|
32
32
|
|
|
33
|
+
# SEQUEL5: Remove
|
|
34
|
+
@convert_invalid_date_time = false
|
|
33
35
|
class << self
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
def convert_invalid_date_time
|
|
37
|
+
Sequel::Deprecation.deprecate("Sequel::MySQL.convert_invalid_date_time", "Call this method on the Database instance")
|
|
38
|
+
@convert_invalid_date_time
|
|
39
|
+
end
|
|
40
|
+
def convert_invalid_date_time=(v)
|
|
41
|
+
Sequel::Deprecation.deprecate("Sequel::MySQL.convert_invalid_date_time=", "Call this method on the Database instance")
|
|
42
|
+
@convert_invalid_date_time = v
|
|
43
|
+
end
|
|
39
44
|
end
|
|
40
|
-
self.convert_invalid_date_time = false
|
|
41
45
|
|
|
42
46
|
# Database class for MySQL databases used with Sequel.
|
|
43
47
|
class Database < Sequel::Database
|
|
@@ -54,7 +58,7 @@ module Sequel
|
|
|
54
58
|
|
|
55
59
|
# Hash of conversion procs for the current database
|
|
56
60
|
attr_reader :conversion_procs
|
|
57
|
-
|
|
61
|
+
|
|
58
62
|
# Whether to convert tinyint columns to bool for the current database
|
|
59
63
|
attr_reader :convert_tinyint_to_bool
|
|
60
64
|
|
|
@@ -227,8 +231,8 @@ module Sequel
|
|
|
227
231
|
|
|
228
232
|
def adapter_initialize
|
|
229
233
|
@conversion_procs = MYSQL_TYPES.dup
|
|
230
|
-
self.convert_tinyint_to_bool = Sequel::MySQL.convert_tinyint_to_bool
|
|
231
|
-
self.convert_invalid_date_time = Sequel::MySQL.convert_invalid_date_time
|
|
234
|
+
self.convert_tinyint_to_bool = Sequel::MySQL.instance_variable_get(:@convert_tinyint_to_bool) # true # SEQUEL5
|
|
235
|
+
self.convert_invalid_date_time = Sequel::MySQL.instance_variable_get(:@convert_invalid_date_time) # false # SEQUEL5
|
|
232
236
|
end
|
|
233
237
|
|
|
234
238
|
# Try to get an accurate number of rows matched using the query
|
|
@@ -288,7 +292,7 @@ module Sequel
|
|
|
288
292
|
# The database name when using the native adapter is always stored in
|
|
289
293
|
# the :database option.
|
|
290
294
|
def database_name
|
|
291
|
-
Sequel::Deprecation.deprecate("Database#database_name", "Instead, use .get
|
|
295
|
+
Sequel::Deprecation.deprecate("Database#database_name", "Instead, use .get(Sequel.function(:DATABASE))")
|
|
292
296
|
@opts[:database]
|
|
293
297
|
end
|
|
294
298
|
|
|
@@ -316,8 +320,7 @@ module Sequel
|
|
|
316
320
|
cps = db.conversion_procs
|
|
317
321
|
cols = r.fetch_fields.map do |f|
|
|
318
322
|
# Pretend tinyint is another integer type if its length is not 1, to
|
|
319
|
-
# avoid casting to boolean if
|
|
320
|
-
# is set.
|
|
323
|
+
# avoid casting to boolean if convert_tinyint_to_bool is set.
|
|
321
324
|
type_proc = f.type == 1 && cast_tinyint_integer?(f) ? cps[2] : cps[f.type]
|
|
322
325
|
[output_identifier(f.name), type_proc, i+=1]
|
|
323
326
|
end
|
|
@@ -373,9 +376,7 @@ module Sequel
|
|
|
373
376
|
|
|
374
377
|
# Handle correct quoting of strings using ::MySQL.quote.
|
|
375
378
|
def literal_string_append(sql, v)
|
|
376
|
-
sql << "'"
|
|
377
|
-
sql << ::Mysql.quote(v)
|
|
378
|
-
sql << "'"
|
|
379
|
+
sql << "'" << ::Mysql.quote(v) << "'"
|
|
379
380
|
end
|
|
380
381
|
|
|
381
382
|
# Yield each row of the given result set r with columns cols
|
|
@@ -171,7 +171,7 @@ module Sequel
|
|
|
171
171
|
|
|
172
172
|
# Set the convert_tinyint_to_bool setting based on the default value.
|
|
173
173
|
def adapter_initialize
|
|
174
|
-
self.convert_tinyint_to_bool = Sequel::MySQL.convert_tinyint_to_bool
|
|
174
|
+
self.convert_tinyint_to_bool = Sequel::MySQL.instance_variable_get(:@convert_tinyint_to_bool) # true # SEQUEL5
|
|
175
175
|
end
|
|
176
176
|
|
|
177
177
|
if NativePreparedStatements
|
|
@@ -222,7 +222,7 @@ module Sequel
|
|
|
222
222
|
# The database name when using the native adapter is always stored in
|
|
223
223
|
# the :database option.
|
|
224
224
|
def database_name
|
|
225
|
-
Sequel::Deprecation.deprecate("Database#database_name", "Instead, use .get
|
|
225
|
+
Sequel::Deprecation.deprecate("Database#database_name", "Instead, use .get(Sequel.function(:DATABASE))")
|
|
226
226
|
@opts[:database]
|
|
227
227
|
end
|
|
228
228
|
|
|
@@ -277,7 +277,7 @@ module Sequel
|
|
|
277
277
|
private
|
|
278
278
|
|
|
279
279
|
# Whether to cast tinyint(1) columns to integer instead of boolean.
|
|
280
|
-
# By default, uses the
|
|
280
|
+
# By default, uses the database's convert_tinyint_to_bool
|
|
281
281
|
# setting. Exists for compatibility with the mysql adapter.
|
|
282
282
|
def convert_tinyint_to_bool?
|
|
283
283
|
@db.convert_tinyint_to_bool
|
|
@@ -303,8 +303,7 @@ module Sequel
|
|
|
303
303
|
|
|
304
304
|
# Handle correct quoting of strings using ::Mysql2::Client#escape.
|
|
305
305
|
def literal_string_append(sql, v)
|
|
306
|
-
|
|
307
|
-
sql << "'" << s << "'"
|
|
306
|
+
sql << "'" << db.synchronize(@opts[:server]){|c| c.escape(v)} << "'"
|
|
308
307
|
end
|
|
309
308
|
end
|
|
310
309
|
end
|
|
@@ -112,9 +112,9 @@ module Sequel
|
|
|
112
112
|
@conversion_procs = ORACLE_TYPES.dup
|
|
113
113
|
end
|
|
114
114
|
|
|
115
|
-
PS_TYPES = {'string'
|
|
116
|
-
'decimal'
|
|
117
|
-
'time'
|
|
115
|
+
PS_TYPES = {'string'=>String, 'integer'=>Integer, 'float'=>Float,
|
|
116
|
+
'decimal'=>Float, 'date'=>Time, 'datetime'=>Time,
|
|
117
|
+
'time'=>Time, 'boolean'=>String, 'blob'=>OCI8::BLOB}#.freeze # SEQUEL5
|
|
118
118
|
def cursor_bind_params(conn, cursor, args)
|
|
119
119
|
i = 0
|
|
120
120
|
args.map do |arg, type|
|
|
@@ -129,11 +129,7 @@ module Sequel
|
|
|
129
129
|
when ::Sequel::SQL::Blob
|
|
130
130
|
arg = ::OCI8::BLOB.new(conn, arg)
|
|
131
131
|
end
|
|
132
|
-
|
|
133
|
-
cursor.bind_param(i, arg, t)
|
|
134
|
-
else
|
|
135
|
-
cursor.bind_param(i, arg, arg.class)
|
|
136
|
-
end
|
|
132
|
+
cursor.bind_param(i, arg, PS_TYPES[type] || arg.class)
|
|
137
133
|
arg
|
|
138
134
|
end
|
|
139
135
|
end
|
|
@@ -287,7 +283,7 @@ module Sequel
|
|
|
287
283
|
defaults = begin
|
|
288
284
|
metadata_dataset.from(:all_tab_cols).
|
|
289
285
|
where(:table_name=>im.call(table)).
|
|
290
|
-
|
|
286
|
+
as_hash(:column_name, :data_default)
|
|
291
287
|
rescue DatabaseError
|
|
292
288
|
{}
|
|
293
289
|
end
|
|
@@ -5,89 +5,20 @@ Sequel.require 'adapters/shared/postgres'
|
|
|
5
5
|
begin
|
|
6
6
|
require 'pg'
|
|
7
7
|
|
|
8
|
+
Sequel::Postgres::PGError = PG::Error if defined?(PG::Error)
|
|
9
|
+
Sequel::Postgres::PGconn = PG::Connection if defined?(PG::Connection)
|
|
10
|
+
Sequel::Postgres::PGresult = PG::Result if defined?(PG::Result)
|
|
11
|
+
|
|
8
12
|
# Work around postgres-pr 0.7.0+ which ships with a pg.rb file
|
|
9
|
-
|
|
13
|
+
unless defined?(PG::Connection)
|
|
14
|
+
raise LoadError unless defined?(PGconn::CONNECTION_OK)
|
|
15
|
+
end
|
|
10
16
|
|
|
11
17
|
Sequel::Postgres::USES_PG = true
|
|
12
18
|
rescue LoadError => e
|
|
13
|
-
Sequel::Postgres::USES_PG = false
|
|
14
19
|
begin
|
|
15
|
-
require 'postgres'
|
|
16
|
-
|
|
17
|
-
# if pg, postgres, or postgres-pr is used.
|
|
18
|
-
class PGconn
|
|
19
|
-
unless method_defined?(:escape_string)
|
|
20
|
-
if self.respond_to?(:escape)
|
|
21
|
-
# If there is no escape_string instance method, but there is an
|
|
22
|
-
# escape class method, use that instead.
|
|
23
|
-
def escape_string(str)
|
|
24
|
-
Sequel::Postgres.force_standard_strings ? str.gsub("'", "''") : self.class.escape(str)
|
|
25
|
-
end
|
|
26
|
-
else
|
|
27
|
-
# Raise an error if no valid string escaping method can be found.
|
|
28
|
-
def escape_string(obj)
|
|
29
|
-
if Sequel::Postgres.force_standard_strings
|
|
30
|
-
str.gsub("'", "''")
|
|
31
|
-
else
|
|
32
|
-
raise Sequel::Error, "string escaping not supported with this postgres driver. Try using ruby-pg, ruby-postgres, or postgres-pr."
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
unless method_defined?(:escape_bytea)
|
|
38
|
-
if self.respond_to?(:escape_bytea)
|
|
39
|
-
# If there is no escape_bytea instance method, but there is an
|
|
40
|
-
# escape_bytea class method, use that instead.
|
|
41
|
-
def escape_bytea(obj)
|
|
42
|
-
self.class.escape_bytea(obj)
|
|
43
|
-
end
|
|
44
|
-
else
|
|
45
|
-
begin
|
|
46
|
-
require 'postgres-pr/typeconv/conv'
|
|
47
|
-
require 'postgres-pr/typeconv/bytea'
|
|
48
|
-
extend Postgres::Conversion
|
|
49
|
-
# If we are using postgres-pr, use the encode_bytea method from
|
|
50
|
-
# that.
|
|
51
|
-
def escape_bytea(obj)
|
|
52
|
-
self.class.encode_bytea(obj)
|
|
53
|
-
end
|
|
54
|
-
instance_eval{alias unescape_bytea decode_bytea}
|
|
55
|
-
rescue
|
|
56
|
-
# If no valid bytea escaping method can be found, create one that
|
|
57
|
-
# raises an error
|
|
58
|
-
def escape_bytea(obj)
|
|
59
|
-
raise Sequel::Error, "bytea escaping not supported with this postgres driver. Try using ruby-pg, ruby-postgres, or postgres-pr."
|
|
60
|
-
end
|
|
61
|
-
# If no valid bytea unescaping method can be found, create one that
|
|
62
|
-
# raises an error
|
|
63
|
-
def self.unescape_bytea(obj)
|
|
64
|
-
raise Sequel::Error, "bytea unescaping not supported with this postgres driver. Try using ruby-pg, ruby-postgres, or postgres-pr."
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
alias_method :finish, :close unless method_defined?(:finish)
|
|
70
|
-
alias_method :async_exec, :exec unless method_defined?(:async_exec)
|
|
71
|
-
unless method_defined?(:block)
|
|
72
|
-
def block(timeout=nil)
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
unless defined?(CONNECTION_OK)
|
|
76
|
-
CONNECTION_OK = -1
|
|
77
|
-
end
|
|
78
|
-
unless method_defined?(:status)
|
|
79
|
-
def status
|
|
80
|
-
CONNECTION_OK
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
class PGresult
|
|
85
|
-
alias_method :nfields, :num_fields unless method_defined?(:nfields)
|
|
86
|
-
alias_method :ntuples, :num_tuples unless method_defined?(:ntuples)
|
|
87
|
-
alias_method :ftype, :type unless method_defined?(:ftype)
|
|
88
|
-
alias_method :fname, :fieldname unless method_defined?(:fname)
|
|
89
|
-
alias_method :cmd_tuples, :cmdtuples unless method_defined?(:cmd_tuples)
|
|
90
|
-
end
|
|
20
|
+
require 'postgres-pr/postgres-compat'
|
|
21
|
+
Sequel::Postgres::USES_PG = false
|
|
91
22
|
rescue LoadError
|
|
92
23
|
raise e
|
|
93
24
|
end
|
|
@@ -95,14 +26,11 @@ end
|
|
|
95
26
|
|
|
96
27
|
module Sequel
|
|
97
28
|
module Postgres
|
|
98
|
-
|
|
99
|
-
|
|
29
|
+
# SEQUEL5: Remove
|
|
100
30
|
TYPE_CONVERTOR = Class.new do
|
|
101
31
|
def bytea(s) ::Sequel::SQL::Blob.new(Adapter.unescape_bytea(s)) end
|
|
102
32
|
end.new
|
|
103
|
-
|
|
104
|
-
# SEQUEL5: Remove
|
|
105
|
-
PG_TYPES[17] = TYPE_CONVERTOR.method(:bytea)
|
|
33
|
+
Sequel::Deprecation.deprecate_constant(self, :TYPE_CONVERTOR)
|
|
106
34
|
|
|
107
35
|
if Sequel::Postgres::USES_PG
|
|
108
36
|
# Whether the given sequel_pg version integer is supported.
|
|
@@ -111,18 +39,22 @@ module Sequel
|
|
|
111
39
|
end
|
|
112
40
|
end
|
|
113
41
|
|
|
42
|
+
# SEQUEL5: Remove
|
|
114
43
|
@use_iso_date_format = true
|
|
115
|
-
|
|
116
44
|
class << self
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
45
|
+
def use_iso_date_format
|
|
46
|
+
Sequel::Deprecation.deprecate("Sequel::Postgres.use_iso_date_format", "Use the :use_iso_date_format Database option instead")
|
|
47
|
+
@use_iso_date_format
|
|
48
|
+
end
|
|
49
|
+
def use_iso_date_format=(v)
|
|
50
|
+
Sequel::Deprecation.deprecate("Sequel::Postgres.use_iso_date_format=", "Use the :use_iso_date_format Database option instead")
|
|
51
|
+
@use_iso_date_format = v
|
|
52
|
+
end
|
|
121
53
|
end
|
|
122
54
|
|
|
123
55
|
# PGconn subclass for connection specific methods used with the
|
|
124
|
-
# pg
|
|
125
|
-
class Adapter <
|
|
56
|
+
# pg or postgres-pr driver.
|
|
57
|
+
class Adapter < PGconn
|
|
126
58
|
# The underlying exception classes to reraise as disconnect errors
|
|
127
59
|
# instead of regular database errors.
|
|
128
60
|
DISCONNECT_ERROR_CLASSES = [IOError, Errno::EPIPE, Errno::ECONNRESET]
|
|
@@ -145,10 +77,49 @@ module Sequel
|
|
|
145
77
|
# errors.
|
|
146
78
|
DISCONNECT_ERROR_RE = /\A#{Regexp.union(disconnect_errors)}/
|
|
147
79
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
80
|
+
if USES_PG
|
|
81
|
+
# Hash of prepared statements for this connection. Keys are
|
|
82
|
+
# string names of the server side prepared statement, and values
|
|
83
|
+
# are SQL strings.
|
|
84
|
+
attr_reader :prepared_statements
|
|
85
|
+
else
|
|
86
|
+
# Make postgres-pr look like pg
|
|
87
|
+
CONNECTION_OK = -1
|
|
88
|
+
|
|
89
|
+
# Escape bytea values. Uses historical format instead of hex
|
|
90
|
+
# format for maximum compatibility.
|
|
91
|
+
def escape_bytea(str)
|
|
92
|
+
# each_byte used instead of [] for 1.9 compatibility
|
|
93
|
+
str.gsub(/[\000-\037\047\134\177-\377]/n){|b| "\\#{sprintf('%o', b.each_byte{|x| break x}).rjust(3, '0')}"}
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Escape strings by doubling apostrophes. This only works if standard
|
|
97
|
+
# conforming strings are used.
|
|
98
|
+
def escape_string(str)
|
|
99
|
+
str.gsub("'", "''")
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
alias finish close
|
|
103
|
+
|
|
104
|
+
def async_exec(sql)
|
|
105
|
+
PGresult.new(@conn.query(sql))
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def block(timeout=nil)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def status
|
|
112
|
+
CONNECTION_OK
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
class PGresult < ::PGresult
|
|
116
|
+
alias nfields num_fields
|
|
117
|
+
alias ntuples num_tuples
|
|
118
|
+
alias ftype type
|
|
119
|
+
alias fname fieldname
|
|
120
|
+
alias cmd_tuples cmdtuples
|
|
121
|
+
end
|
|
122
|
+
end
|
|
152
123
|
|
|
153
124
|
# Raise a Sequel::DatabaseDisconnectError if a one of the disconnect
|
|
154
125
|
# error classes is raised, or a PGError is raised and the connection
|
|
@@ -258,6 +229,10 @@ module Sequel
|
|
|
258
229
|
conn.set_notice_receiver(&receiver)
|
|
259
230
|
end
|
|
260
231
|
else
|
|
232
|
+
unless typecast_value_boolean(@opts.fetch(:force_standard_strings, Postgres.instance_variable_get(:@force_standard_strings))) # , true)) # SEQUEL5
|
|
233
|
+
raise Error, "Cannot create connection using postgres-pr unless force_standard_strings is set"
|
|
234
|
+
end
|
|
235
|
+
|
|
261
236
|
conn = Adapter.connect(
|
|
262
237
|
(opts[:host] unless blank_object?(opts[:host])),
|
|
263
238
|
opts[:port] || 5432,
|
|
@@ -311,7 +286,7 @@ module Sequel
|
|
|
311
286
|
end
|
|
312
287
|
end
|
|
313
288
|
end
|
|
314
|
-
|
|
289
|
+
add_conversion_proc(1082, pr)
|
|
315
290
|
end
|
|
316
291
|
|
|
317
292
|
# Disconnect given connection
|
|
@@ -390,8 +365,12 @@ module Sequel
|
|
|
390
365
|
b << buf while buf = conn.get_copy_data
|
|
391
366
|
b
|
|
392
367
|
end
|
|
368
|
+
rescue => e
|
|
369
|
+
raise_error(e, :disconnect=>true)
|
|
393
370
|
ensure
|
|
394
|
-
|
|
371
|
+
if buf && !e
|
|
372
|
+
raise DatabaseDisconnectError, "disconnecting as a partial COPY may leave the connection in an unusable state"
|
|
373
|
+
end
|
|
395
374
|
end
|
|
396
375
|
end
|
|
397
376
|
end
|
|
@@ -544,10 +523,10 @@ module Sequel
|
|
|
544
523
|
# Add the primary_keys and primary_key_sequences instance variables,
|
|
545
524
|
# so we can get the correct return values for inserted rows.
|
|
546
525
|
def adapter_initialize
|
|
547
|
-
@use_iso_date_format = typecast_value_boolean(@opts.fetch(:use_iso_date_format, Postgres.use_iso_date_format))
|
|
526
|
+
@use_iso_date_format = typecast_value_boolean(@opts.fetch(:use_iso_date_format, Postgres.instance_variable_get(:@use_iso_date_format))) # , true)) # SEQUEL5
|
|
548
527
|
initialize_postgres_adapter
|
|
549
|
-
|
|
550
|
-
|
|
528
|
+
add_conversion_proc(17, method(:unescape_bytea)) if USES_PG
|
|
529
|
+
add_conversion_proc(1082, TYPE_TRANSLATOR.method(:date)) if @use_iso_date_format
|
|
551
530
|
self.convert_infinite_timestamps = @opts[:convert_infinite_timestamps]
|
|
552
531
|
end
|
|
553
532
|
|
|
@@ -556,7 +535,7 @@ module Sequel
|
|
|
556
535
|
begin
|
|
557
536
|
yield
|
|
558
537
|
rescue => e
|
|
559
|
-
raise_error(e, :classes=>
|
|
538
|
+
raise_error(e, :classes=>database_error_classes)
|
|
560
539
|
end
|
|
561
540
|
end
|
|
562
541
|
|
|
@@ -567,8 +546,15 @@ module Sequel
|
|
|
567
546
|
sqls
|
|
568
547
|
end
|
|
569
548
|
|
|
549
|
+
if USES_PG
|
|
550
|
+
def unescape_bytea(s)
|
|
551
|
+
::Sequel::SQL::Blob.new(Adapter.unescape_bytea(s))
|
|
552
|
+
end
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
DATABASE_ERROR_CLASSES = [PGError].freeze
|
|
570
556
|
def database_error_classes
|
|
571
|
-
|
|
557
|
+
DATABASE_ERROR_CLASSES
|
|
572
558
|
end
|
|
573
559
|
|
|
574
560
|
def disconnect_error?(exception, opts)
|
|
@@ -579,7 +565,7 @@ module Sequel
|
|
|
579
565
|
|
|
580
566
|
def database_exception_sqlstate(exception, opts)
|
|
581
567
|
if exception.respond_to?(:result) && (result = exception.result)
|
|
582
|
-
result.error_field(
|
|
568
|
+
result.error_field(PGresult::PG_DIAG_SQLSTATE)
|
|
583
569
|
end
|
|
584
570
|
end
|
|
585
571
|
|
|
@@ -885,3 +871,4 @@ end
|
|
|
885
871
|
|
|
886
872
|
# SEQUEL5: Remove
|
|
887
873
|
SEQUEL_POSTGRES_USES_PG = Sequel::Postgres::USES_PG
|
|
874
|
+
Sequel::Deprecation.deprecate_constant(Object, :SEQUEL_POSTGRES_USES_PG)
|