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.
Files changed (177) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +134 -0
  3. data/Rakefile +1 -1
  4. data/doc/release_notes/4.48.0.txt +293 -0
  5. data/lib/sequel/adapters/ado/access.rb +2 -1
  6. data/lib/sequel/adapters/do/postgres.rb +5 -2
  7. data/lib/sequel/adapters/ibmdb.rb +24 -7
  8. data/lib/sequel/adapters/jdbc.rb +36 -22
  9. data/lib/sequel/adapters/jdbc/db2.rb +12 -3
  10. data/lib/sequel/adapters/jdbc/derby.rb +4 -5
  11. data/lib/sequel/adapters/jdbc/oracle.rb +16 -2
  12. data/lib/sequel/adapters/jdbc/postgresql.rb +43 -18
  13. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +9 -7
  14. data/lib/sequel/adapters/jdbc/sqlserver.rb +11 -4
  15. data/lib/sequel/adapters/mock.rb +24 -19
  16. data/lib/sequel/adapters/mysql.rb +17 -16
  17. data/lib/sequel/adapters/mysql2.rb +4 -5
  18. data/lib/sequel/adapters/oracle.rb +5 -9
  19. data/lib/sequel/adapters/postgres.rb +89 -102
  20. data/lib/sequel/adapters/shared/db2.rb +22 -6
  21. data/lib/sequel/adapters/shared/mssql.rb +5 -4
  22. data/lib/sequel/adapters/shared/mysql.rb +75 -24
  23. data/lib/sequel/adapters/shared/postgres.rb +196 -94
  24. data/lib/sequel/adapters/shared/sqlanywhere.rb +23 -10
  25. data/lib/sequel/adapters/shared/sqlite.rb +72 -82
  26. data/lib/sequel/adapters/sqlanywhere.rb +4 -1
  27. data/lib/sequel/adapters/sqlite.rb +5 -3
  28. data/lib/sequel/adapters/swift/postgres.rb +5 -2
  29. data/lib/sequel/adapters/tinytds.rb +0 -5
  30. data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -1
  31. data/lib/sequel/adapters/utils/pg_types.rb +2 -76
  32. data/lib/sequel/core.rb +2 -2
  33. data/lib/sequel/database/connecting.rb +5 -5
  34. data/lib/sequel/database/dataset.rb +6 -3
  35. data/lib/sequel/database/misc.rb +1 -1
  36. data/lib/sequel/database/query.rb +3 -0
  37. data/lib/sequel/database/schema_methods.rb +1 -1
  38. data/lib/sequel/dataset/actions.rb +18 -10
  39. data/lib/sequel/dataset/graph.rb +1 -1
  40. data/lib/sequel/dataset/misc.rb +1 -0
  41. data/lib/sequel/dataset/prepared_statements.rb +3 -3
  42. data/lib/sequel/dataset/query.rb +19 -8
  43. data/lib/sequel/extensions/core_extensions.rb +4 -1
  44. data/lib/sequel/extensions/duplicate_columns_handler.rb +1 -1
  45. data/lib/sequel/extensions/empty_array_ignore_nulls.rb +3 -0
  46. data/lib/sequel/extensions/filter_having.rb +2 -0
  47. data/lib/sequel/extensions/freeze_datasets.rb +2 -0
  48. data/lib/sequel/extensions/from_block.rb +1 -1
  49. data/lib/sequel/extensions/graph_each.rb +2 -2
  50. data/lib/sequel/extensions/hash_aliases.rb +2 -0
  51. data/lib/sequel/extensions/identifier_mangling.rb +0 -7
  52. data/lib/sequel/extensions/meta_def.rb +2 -0
  53. data/lib/sequel/extensions/migration.rb +6 -6
  54. data/lib/sequel/extensions/no_auto_literal_strings.rb +1 -1
  55. data/lib/sequel/extensions/pagination.rb +1 -1
  56. data/lib/sequel/extensions/pg_array.rb +207 -130
  57. data/lib/sequel/extensions/pg_hstore.rb +38 -20
  58. data/lib/sequel/extensions/pg_inet.rb +18 -6
  59. data/lib/sequel/extensions/pg_interval.rb +19 -12
  60. data/lib/sequel/extensions/pg_json.rb +25 -14
  61. data/lib/sequel/extensions/pg_json_ops.rb +2 -2
  62. data/lib/sequel/extensions/pg_range.rb +133 -100
  63. data/lib/sequel/extensions/pg_range_ops.rb +4 -3
  64. data/lib/sequel/extensions/pg_row.rb +68 -39
  65. data/lib/sequel/extensions/pg_row_ops.rb +11 -5
  66. data/lib/sequel/extensions/query_literals.rb +2 -0
  67. data/lib/sequel/extensions/ruby18_symbol_extensions.rb +2 -0
  68. data/lib/sequel/extensions/s.rb +1 -1
  69. data/lib/sequel/extensions/schema_dumper.rb +24 -24
  70. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +3 -1
  71. data/lib/sequel/extensions/sequel_4_dataset_methods.rb +83 -0
  72. data/lib/sequel/extensions/set_overrides.rb +2 -2
  73. data/lib/sequel/extensions/string_agg.rb +0 -1
  74. data/lib/sequel/extensions/symbol_aref.rb +0 -4
  75. data/lib/sequel/model.rb +25 -57
  76. data/lib/sequel/model/associations.rb +14 -5
  77. data/lib/sequel/model/base.rb +96 -32
  78. data/lib/sequel/plugins/association_pks.rb +73 -46
  79. data/lib/sequel/plugins/association_proxies.rb +1 -1
  80. data/lib/sequel/plugins/auto_validations.rb +6 -2
  81. data/lib/sequel/plugins/boolean_readers.rb +1 -1
  82. data/lib/sequel/plugins/caching.rb +19 -13
  83. data/lib/sequel/plugins/class_table_inheritance.rb +19 -10
  84. data/lib/sequel/plugins/column_conflicts.rb +7 -2
  85. data/lib/sequel/plugins/column_select.rb +1 -1
  86. data/lib/sequel/plugins/csv_serializer.rb +8 -8
  87. data/lib/sequel/plugins/defaults_setter.rb +10 -0
  88. data/lib/sequel/plugins/eager_each.rb +1 -1
  89. data/lib/sequel/plugins/force_encoding.rb +2 -2
  90. data/lib/sequel/plugins/hook_class_methods.rb +9 -12
  91. data/lib/sequel/plugins/identifier_columns.rb +2 -0
  92. data/lib/sequel/plugins/instance_filters.rb +3 -1
  93. data/lib/sequel/plugins/instance_hooks.rb +17 -9
  94. data/lib/sequel/plugins/json_serializer.rb +17 -10
  95. data/lib/sequel/plugins/lazy_attributes.rb +8 -7
  96. data/lib/sequel/plugins/modification_detection.rb +3 -0
  97. data/lib/sequel/plugins/nested_attributes.rb +5 -1
  98. data/lib/sequel/plugins/pg_array_associations.rb +5 -0
  99. data/lib/sequel/plugins/prepared_statements.rb +1 -0
  100. data/lib/sequel/plugins/rcte_tree.rb +4 -4
  101. data/lib/sequel/plugins/serialization.rb +3 -10
  102. data/lib/sequel/plugins/single_table_inheritance.rb +2 -2
  103. data/lib/sequel/plugins/split_values.rb +6 -5
  104. data/lib/sequel/plugins/static_cache.rb +31 -25
  105. data/lib/sequel/plugins/subset_conditions.rb +3 -1
  106. data/lib/sequel/plugins/table_select.rb +1 -1
  107. data/lib/sequel/plugins/touch.rb +2 -1
  108. data/lib/sequel/plugins/validation_class_methods.rb +5 -6
  109. data/lib/sequel/plugins/validation_helpers.rb +2 -4
  110. data/lib/sequel/plugins/xml_serializer.rb +4 -4
  111. data/lib/sequel/sql.rb +2 -2
  112. data/lib/sequel/version.rb +1 -1
  113. data/spec/adapters/db2_spec.rb +115 -14
  114. data/spec/adapters/mysql_spec.rb +78 -28
  115. data/spec/adapters/oracle_spec.rb +24 -24
  116. data/spec/adapters/postgres_spec.rb +38 -24
  117. data/spec/adapters/sqlanywhere_spec.rb +88 -86
  118. data/spec/adapters/sqlite_spec.rb +29 -24
  119. data/spec/core/connection_pool_spec.rb +17 -0
  120. data/spec/core/database_spec.rb +6 -0
  121. data/spec/core/dataset_spec.rb +46 -36
  122. data/spec/core/schema_spec.rb +16 -0
  123. data/spec/core/spec_helper.rb +1 -0
  124. data/spec/core_extensions_spec.rb +6 -2
  125. data/spec/extensions/active_model_spec.rb +1 -1
  126. data/spec/extensions/arbitrary_servers_spec.rb +1 -1
  127. data/spec/extensions/association_pks_spec.rb +34 -2
  128. data/spec/extensions/auto_literal_strings_spec.rb +5 -1
  129. data/spec/extensions/auto_validations_spec.rb +2 -0
  130. data/spec/extensions/boolean_readers_spec.rb +1 -1
  131. data/spec/extensions/boolean_subsets_spec.rb +1 -1
  132. data/spec/extensions/class_table_inheritance_spec.rb +48 -2
  133. data/spec/extensions/column_conflicts_spec.rb +11 -0
  134. data/spec/extensions/connection_validator_spec.rb +1 -1
  135. data/spec/extensions/dataset_associations_spec.rb +8 -8
  136. data/spec/extensions/defaults_setter_spec.rb +1 -1
  137. data/spec/extensions/filter_having_spec.rb +5 -3
  138. data/spec/extensions/hash_aliases_spec.rb +3 -1
  139. data/spec/extensions/identifier_columns_spec.rb +3 -1
  140. data/spec/extensions/implicit_subquery_spec.rb +4 -2
  141. data/spec/extensions/json_serializer_spec.rb +18 -0
  142. data/spec/extensions/lazy_attributes_spec.rb +3 -3
  143. data/spec/extensions/meta_def_spec.rb +9 -0
  144. data/spec/extensions/migration_spec.rb +3 -3
  145. data/spec/extensions/nested_attributes_spec.rb +14 -3
  146. data/spec/extensions/no_auto_literal_strings_spec.rb +8 -4
  147. data/spec/extensions/pg_array_associations_spec.rb +29 -18
  148. data/spec/extensions/pg_array_spec.rb +44 -25
  149. data/spec/extensions/pg_hstore_spec.rb +10 -0
  150. data/spec/extensions/pg_inet_spec.rb +26 -0
  151. data/spec/extensions/pg_interval_spec.rb +20 -0
  152. data/spec/extensions/pg_json_spec.rb +24 -0
  153. data/spec/extensions/pg_range_spec.rb +98 -14
  154. data/spec/extensions/pg_row_spec.rb +14 -4
  155. data/spec/extensions/prepared_statements_safe_spec.rb +1 -1
  156. data/spec/extensions/query_literals_spec.rb +3 -1
  157. data/spec/extensions/schema_dumper_spec.rb +96 -98
  158. data/spec/extensions/sequel_3_dataset_methods_spec.rb +10 -6
  159. data/spec/extensions/sequel_4_dataset_methods_spec.rb +121 -0
  160. data/spec/extensions/single_table_inheritance_spec.rb +1 -1
  161. data/spec/extensions/spec_helper.rb +7 -1
  162. data/spec/extensions/static_cache_spec.rb +75 -24
  163. data/spec/extensions/string_agg_spec.rb +1 -1
  164. data/spec/extensions/touch_spec.rb +9 -0
  165. data/spec/extensions/validation_helpers_spec.rb +9 -3
  166. data/spec/extensions/whitelist_security_spec.rb +26 -0
  167. data/spec/integration/dataset_test.rb +45 -44
  168. data/spec/integration/plugin_test.rb +20 -0
  169. data/spec/integration/prepared_statement_test.rb +3 -0
  170. data/spec/integration/schema_test.rb +21 -1
  171. data/spec/integration/transaction_test.rb +40 -40
  172. data/spec/model/class_dataset_methods_spec.rb +14 -4
  173. data/spec/model/dataset_methods_spec.rb +12 -3
  174. data/spec/model/model_spec.rb +8 -0
  175. metadata +6 -4
  176. data/spec/adapters/firebird_spec.rb +0 -405
  177. data/spec/adapters/informix_spec.rb +0 -100
@@ -28,7 +28,8 @@ module Sequel
28
28
  end
29
29
  end
30
30
 
31
- class TypeConvertor
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
- map[:SqlAnywhereBoolean]
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
- class TypeConvertor
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] = TypeConvertor::INSTANCE.method(:MSSQLRubyTime)
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)
@@ -52,7 +52,7 @@ module Sequel
52
52
  @autoid = case v
53
53
  when Integer
54
54
  i = v - 1
55
- proc{Sequel.synchronize{i+=1}}
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
- s = @sqls.dup
132
- @sqls.clear
133
- s
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
- v = ds.autoid if ds
169
- _autoid(sql, v || @autoid, (ds if v))
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
- # Whether to convert invalid date time values by default.
35
- #
36
- # Only applies to Sequel::Database instances created after this
37
- # has been set.
38
- attr_accessor :convert_invalid_date_time
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{DATABASE{}}")
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 Sequel::MySQL.convert_tinyint_to_bool
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{DATABASE{}}")
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 opposite of the database's convert_tinyint_to_bool
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
- s = db.synchronize(@opts[:server]){|c| c.escape(v)}
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'.freeze=>String, 'integer'.freeze=>Integer, 'float'.freeze=>Float,
116
- 'decimal'.freeze=>Float, 'date'.freeze=>Time, 'datetime'.freeze=>Time,
117
- 'time'.freeze=>Time, 'boolean'.freeze=>String, 'blob'.freeze=>OCI8::BLOB}
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
- if t = PS_TYPES[type]
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
- to_hash(:column_name, :data_default)
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
- raise LoadError unless defined?(PGconn::CONNECTION_OK)
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
- # Attempt to get uniform behavior for the PGconn object no matter
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
- CONVERTED_EXCEPTIONS << PGError
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
- # As an optimization, Sequel sets the date style to ISO, so that PostgreSQL provides
118
- # the date in a known format that Sequel can parse faster. This can be turned off
119
- # if you require a date style other than ISO.
120
- attr_accessor :use_iso_date_format
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, postgres, or postgres-pr driver.
125
- class Adapter < ::PGconn
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
- # Hash of prepared statements for this connection. Keys are
149
- # string names of the server side prepared statement, and values
150
- # are SQL strings.
151
- attr_reader(:prepared_statements) if USES_PG
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
- conversion_procs[1082] = pr
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
- raise DatabaseDisconnectError, "disconnecting as a partial COPY may leave the connection in an unusable state" if buf
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
- conversion_procs[17] = TYPE_CONVERTOR.method(:bytea)
550
- conversion_procs[1082] = TYPE_TRANSLATOR.method(:date) if @use_iso_date_format
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=>CONVERTED_EXCEPTIONS)
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
- [PGError]
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(::PGresult::PG_DIAG_SQLSTATE)
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)