sequel 4.34.0 → 4.35.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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +30 -0
  3. data/Rakefile +14 -17
  4. data/doc/object_model.rdoc +4 -4
  5. data/doc/release_notes/4.35.0.txt +130 -0
  6. data/doc/schema_modification.rdoc +8 -3
  7. data/doc/security.rdoc +3 -3
  8. data/lib/sequel/adapters/ado.rb +2 -2
  9. data/lib/sequel/adapters/ado/access.rb +6 -6
  10. data/lib/sequel/adapters/ado/mssql.rb +2 -2
  11. data/lib/sequel/adapters/amalgalite.rb +6 -6
  12. data/lib/sequel/adapters/cubrid.rb +4 -4
  13. data/lib/sequel/adapters/do.rb +2 -2
  14. data/lib/sequel/adapters/do/mysql.rb +1 -1
  15. data/lib/sequel/adapters/do/postgres.rb +1 -1
  16. data/lib/sequel/adapters/do/sqlite3.rb +1 -1
  17. data/lib/sequel/adapters/ibmdb.rb +6 -6
  18. data/lib/sequel/adapters/jdbc.rb +15 -15
  19. data/lib/sequel/adapters/jdbc/db2.rb +1 -1
  20. data/lib/sequel/adapters/jdbc/derby.rb +3 -3
  21. data/lib/sequel/adapters/jdbc/h2.rb +3 -3
  22. data/lib/sequel/adapters/jdbc/hsqldb.rb +2 -2
  23. data/lib/sequel/adapters/jdbc/mssql.rb +1 -1
  24. data/lib/sequel/adapters/jdbc/mysql.rb +1 -1
  25. data/lib/sequel/adapters/jdbc/oracle.rb +1 -1
  26. data/lib/sequel/adapters/jdbc/postgresql.rb +2 -2
  27. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +1 -1
  28. data/lib/sequel/adapters/jdbc/sqlite.rb +1 -1
  29. data/lib/sequel/adapters/jdbc/transactions.rb +10 -10
  30. data/lib/sequel/adapters/mock.rb +1 -1
  31. data/lib/sequel/adapters/mysql.rb +2 -2
  32. data/lib/sequel/adapters/mysql2.rb +2 -2
  33. data/lib/sequel/adapters/odbc.rb +2 -2
  34. data/lib/sequel/adapters/odbc/mssql.rb +2 -2
  35. data/lib/sequel/adapters/oracle.rb +9 -9
  36. data/lib/sequel/adapters/postgres.rb +3 -3
  37. data/lib/sequel/adapters/shared/mssql.rb +36 -8
  38. data/lib/sequel/adapters/shared/oracle.rb +15 -0
  39. data/lib/sequel/adapters/shared/postgres.rb +22 -1
  40. data/lib/sequel/adapters/sqlanywhere.rb +1 -1
  41. data/lib/sequel/adapters/sqlite.rb +7 -7
  42. data/lib/sequel/adapters/swift.rb +3 -3
  43. data/lib/sequel/adapters/swift/mysql.rb +1 -1
  44. data/lib/sequel/adapters/swift/postgres.rb +1 -1
  45. data/lib/sequel/adapters/swift/sqlite.rb +1 -1
  46. data/lib/sequel/adapters/tinytds.rb +5 -7
  47. data/lib/sequel/database/logging.rb +18 -3
  48. data/lib/sequel/database/misc.rb +19 -8
  49. data/lib/sequel/database/schema_generator.rb +7 -2
  50. data/lib/sequel/database/schema_methods.rb +9 -2
  51. data/lib/sequel/database/transactions.rb +52 -18
  52. data/lib/sequel/dataset/actions.rb +24 -19
  53. data/lib/sequel/dataset/features.rb +5 -0
  54. data/lib/sequel/dataset/query.rb +6 -0
  55. data/lib/sequel/extensions/_pretty_table.rb +1 -1
  56. data/lib/sequel/extensions/error_sql.rb +3 -3
  57. data/lib/sequel/extensions/pg_range.rb +10 -1
  58. data/lib/sequel/extensions/schema_dumper.rb +8 -5
  59. data/lib/sequel/extensions/server_logging.rb +61 -0
  60. data/lib/sequel/extensions/sql_comments.rb +91 -0
  61. data/lib/sequel/model/associations.rb +40 -8
  62. data/lib/sequel/model/base.rb +19 -5
  63. data/lib/sequel/plugins/class_table_inheritance.rb +12 -0
  64. data/lib/sequel/plugins/delay_add_association.rb +1 -0
  65. data/lib/sequel/plugins/json_serializer.rb +10 -2
  66. data/lib/sequel/version.rb +1 -1
  67. data/spec/adapter_spec.rb +4 -0
  68. data/spec/adapters/mysql_spec.rb +1 -1
  69. data/spec/adapters/postgres_spec.rb +3 -2
  70. data/spec/core/connection_pool_spec.rb +2 -0
  71. data/spec/core/database_spec.rb +49 -0
  72. data/spec/core/dataset_spec.rb +25 -1
  73. data/spec/core/mock_adapter_spec.rb +3 -1
  74. data/spec/core/schema_generator_spec.rb +1 -1
  75. data/spec/core_model_spec.rb +2 -0
  76. data/spec/core_spec.rb +1 -0
  77. data/spec/extensions/delay_add_association_spec.rb +22 -0
  78. data/spec/extensions/json_serializer_spec.rb +6 -0
  79. data/spec/extensions/pg_range_spec.rb +30 -2
  80. data/spec/extensions/schema_dumper_spec.rb +3 -2
  81. data/spec/extensions/server_logging_spec.rb +45 -0
  82. data/spec/extensions/sql_comments_spec.rb +27 -0
  83. data/spec/files/reversible_migrations/006_reversible.rb +10 -0
  84. data/spec/files/reversible_migrations/007_reversible.rb +10 -0
  85. data/spec/integration/dataset_test.rb +28 -2
  86. data/spec/integration/migrator_test.rb +23 -1
  87. data/spec/integration/schema_test.rb +12 -32
  88. data/spec/integration/transaction_test.rb +10 -0
  89. data/spec/integration/type_test.rb +1 -1
  90. data/spec/model/eager_loading_spec.rb +16 -0
  91. data/spec/model/record_spec.rb +9 -0
  92. data/spec/model_no_assoc_spec.rb +1 -0
  93. data/spec/model_spec.rb +1 -0
  94. data/spec/plugin_spec.rb +1 -0
  95. metadata +16 -2
@@ -116,31 +116,35 @@ module Sequel
116
116
  # :sql_log_level :: Method to use to log SQL to a logger, :info by default.
117
117
  #
118
118
  # All options given are also passed to the connection pool.
119
- def initialize(opts = OPTS, &block)
119
+ def initialize(opts = OPTS)
120
120
  @opts ||= opts
121
121
  @opts = connection_pool_default_options.merge(@opts)
122
122
  @loggers = Array(@opts[:logger]) + Array(@opts[:loggers])
123
- self.log_warn_duration = @opts[:log_warn_duration]
124
- block ||= proc{|server| connect(server)}
125
123
  @opts[:servers] = {} if @opts[:servers].is_a?(String)
126
124
  @sharded = !!@opts[:servers]
127
125
  @opts[:adapter_class] = self.class
128
-
129
126
  @opts[:single_threaded] = @single_threaded = typecast_value_boolean(@opts.fetch(:single_threaded, Database.single_threaded))
130
- @schemas = {}
131
127
  @default_string_column_size = @opts[:default_string_column_size] || DEFAULT_STRING_COLUMN_SIZE
128
+
129
+ @schemas = {}
132
130
  @prepared_statements = {}
133
131
  @transactions = {}
132
+ @symbol_literal_cache = {}
133
+
134
134
  @identifier_input_method = nil
135
135
  @identifier_output_method = nil
136
136
  @quote_identifiers = nil
137
137
  @timezone = nil
138
+
138
139
  @dataset_class = dataset_class_default
139
140
  @cache_schema = typecast_value_boolean(@opts.fetch(:cache_schema, true))
140
141
  @dataset_modules = []
141
- @symbol_literal_cache = {}
142
142
  @schema_type_classes = SCHEMA_TYPE_CLASSES.dup
143
+
143
144
  self.sql_log_level = @opts[:sql_log_level] ? @opts[:sql_log_level].to_sym : :info
145
+ self.log_warn_duration = @opts[:log_warn_duration]
146
+ self.log_connection_info = typecast_value_boolean(@opts[:log_connection_info])
147
+
144
148
  @pool = ConnectionPool.get_pool(self, @opts)
145
149
 
146
150
  reset_identifier_mangling
@@ -166,7 +170,7 @@ module Sequel
166
170
  synchronize(opts[:server]) do |conn|
167
171
  if h = _trans(conn)
168
172
  raise Error, "cannot call after_commit in a prepared transaction" if h[:prepare]
169
- (h[:after_commit] ||= []) << block
173
+ add_transaction_hook(conn, :after_commit, block)
170
174
  else
171
175
  yield
172
176
  end
@@ -183,7 +187,7 @@ module Sequel
183
187
  synchronize(opts[:server]) do |conn|
184
188
  if h = _trans(conn)
185
189
  raise Error, "cannot call after_rollback in a prepared transaction" if h[:prepare]
186
- (h[:after_rollback] ||= []) << block
190
+ add_transaction_hook(conn, :after_rollback, block)
187
191
  end
188
192
  end
189
193
  end
@@ -337,6 +341,13 @@ module Sequel
337
341
  def adapter_initialize
338
342
  end
339
343
 
344
+ # Set the given callable as a hook to be called. Type should be either
345
+ # :after_commit or :after_rollback.
346
+ def add_transaction_hook(conn, type, block)
347
+ hooks = _trans(conn)[type] ||= []
348
+ hooks << block
349
+ end
350
+
340
351
  # Returns true when the object is considered blank.
341
352
  # The only objects that are blank are nil, false,
342
353
  # strings with all whitespace, and ones that respond
@@ -18,8 +18,7 @@ module Sequel
18
18
  # the {"Schema Modification" guide}[rdoc-ref:doc/schema_modification.rdoc].
19
19
  class CreateTableGenerator
20
20
  # Classes specifying generic types that Sequel will convert to database-specific types.
21
- GENERIC_TYPES=[String, Integer, Fixnum, Bignum, Float, Numeric, BigDecimal,
22
- Date, DateTime, Time, File, TrueClass, FalseClass]
21
+ GENERIC_TYPES=%w'String Integer Fixnum Float Numeric BigDecimal Date DateTime Time File TrueClass FalseClass'
23
22
 
24
23
  # Return the column hashes created by this generator
25
24
  attr_reader :columns
@@ -41,6 +40,12 @@ module Sequel
41
40
  instance_eval(&block) if block
42
41
  @columns.unshift(@primary_key) if @primary_key && !has_column?(primary_key_name)
43
42
  end
43
+
44
+ # Use custom Bignum method to use :Bignum instead of Bignum class, to work
45
+ # correctly in cases where Bignum is the same as Integer.
46
+ def Bignum(name, opts=OPTS)
47
+ column(name, :Bignum, opts)
48
+ end
44
49
 
45
50
  # Add a method for each of the given types that creates a column
46
51
  # with that type as a constant. Types given should either already
@@ -108,7 +108,7 @@ module Sequel
108
108
  # be option hashes, so long as the option hashes have a :table
109
109
  # entry giving the table referenced:
110
110
  #
111
- # create_join_table(:cat_id=>{:table=>:cats, :type=>Bignum}, :dog_id=>:dogs)
111
+ # create_join_table(:cat_id=>{:table=>:cats, :type=>:Bignum}, :dog_id=>:dogs)
112
112
  #
113
113
  # You can provide a second argument which is a table options hash:
114
114
  #
@@ -884,7 +884,14 @@ module Sequel
884
884
 
885
885
  # SQL fragment specifying the type of a given column.
886
886
  def type_literal(column)
887
- column[:type].is_a?(Class) ? type_literal_generic(column) : type_literal_specific(column)
887
+ case column[:type]
888
+ when Class
889
+ type_literal_generic(column)
890
+ when :Bignum
891
+ type_literal_generic_bignum(column)
892
+ else
893
+ type_literal_specific(column)
894
+ end
888
895
  end
889
896
 
890
897
  # SQL fragment specifying the full type of a column,
@@ -80,11 +80,14 @@ module Sequel
80
80
  # appropriately. Valid values true, :on, false, :off, :local (9.1+),
81
81
  # and :remote_write (9.2+).
82
82
  def transaction(opts=OPTS, &block)
83
+ opts = Hash[opts]
83
84
  if retry_on = opts[:retry_on]
84
85
  tot_retries = opts.fetch(:num_retries, 5)
85
86
  num_retries = 0 unless tot_retries.nil?
86
87
  begin
87
- transaction(Hash[opts].merge!(:retry_on=>nil, :retrying=>true), &block)
88
+ opts[:retry_on] = nil
89
+ opts[:retrying] = true
90
+ transaction(opts, &block)
88
91
  rescue *retry_on => e
89
92
  if num_retries
90
93
  num_retries += 1
@@ -99,21 +102,40 @@ module Sequel
99
102
  end
100
103
  else
101
104
  synchronize(opts[:server]) do |conn|
102
- if opts[:savepoint] == :only && supports_savepoints? && !_trans(conn)
103
- return yield(conn)
105
+ if opts[:savepoint] == :only
106
+ if supports_savepoints?
107
+ if _trans(conn)
108
+ opts[:savepoint] = true
109
+ else
110
+ return yield(conn)
111
+ end
112
+ else
113
+ opts[:savepoint] = false
114
+ end
104
115
  end
116
+
105
117
  if already_in_transaction?(conn, opts)
118
+ if opts[:rollback] == :always && !opts.has_key?(:savepoint)
119
+ if supports_savepoints?
120
+ opts[:savepoint] = true
121
+ else
122
+ raise Sequel::Error, "cannot set :rollback=>:always transaction option if already inside a transaction"
123
+ end
124
+ end
125
+
106
126
  if opts[:savepoint] != false && (stack = _trans(conn)[:savepoints]) && stack.last
107
- _transaction(conn, Hash[opts].merge!(:savepoint=>true), &block)
108
- else
127
+ opts[:savepoint] = true
128
+ end
129
+
130
+ unless opts[:savepoint]
109
131
  if opts[:retrying]
110
132
  raise Sequel::Error, "cannot set :retry_on options if you are already inside a transaction"
111
133
  end
112
134
  return yield(conn)
113
135
  end
114
- else
115
- _transaction(conn, opts, &block)
116
136
  end
137
+
138
+ _transaction(conn, opts, &block)
117
139
  end
118
140
  end
119
141
  end
@@ -174,12 +196,12 @@ module Sequel
174
196
 
175
197
  # Add the current thread to the list of active transactions
176
198
  def add_transaction(conn, opts)
177
- hash = {}
199
+ hash = transaction_options(conn, opts)
178
200
 
179
201
  if supports_savepoints?
180
- if _trans(conn)
181
- hash = nil
182
- _trans(conn)[:savepoints].push(opts[:auto_savepoint])
202
+ if t = _trans(conn)
203
+ t[:savepoints].push(opts[:auto_savepoint])
204
+ return
183
205
  else
184
206
  hash[:savepoints] = [opts[:auto_savepoint]]
185
207
  if (prep = opts[:prepare]) && supports_prepared_transactions?
@@ -190,9 +212,7 @@ module Sequel
190
212
  hash[:prepare] = prep
191
213
  end
192
214
 
193
- if hash
194
- Sequel.synchronize{@transactions[conn] = hash}
195
- end
215
+ Sequel.synchronize{@transactions[conn] = hash}
196
216
  end
197
217
 
198
218
  # Whether the current thread/connection is already inside a transaction
@@ -200,6 +220,12 @@ module Sequel
200
220
  _trans(conn) && (!supports_savepoints? || !opts[:savepoint])
201
221
  end
202
222
 
223
+ # Derive the transaction hash from the options passed to the transaction.
224
+ # Meant to be overridden.
225
+ def transaction_options(conn, opts)
226
+ {}
227
+ end
228
+
203
229
  # Issue query to begin a new savepoint.
204
230
  def begin_savepoint(conn, opts)
205
231
  log_connection_execute(conn, begin_savepoint_sql(savepoint_level(conn)-1))
@@ -279,15 +305,23 @@ module Sequel
279
305
  :execute
280
306
  end
281
307
 
308
+ # Retrieve the transaction hooks that should be run for the given
309
+ # connection and commit status.
310
+ def transaction_hooks(conn, committed)
311
+ if !supports_savepoints? || savepoint_level(conn) == 1
312
+ _trans(conn)[committed ? :after_commit : :after_rollback]
313
+ end
314
+ end
315
+
282
316
  # Remove the current thread from the list of active transactions
283
317
  def remove_transaction(conn, committed)
318
+ callbacks = transaction_hooks(conn, committed)
319
+
284
320
  if transaction_finished?(conn)
285
- callbacks = _trans(conn)[committed ? :after_commit : :after_rollback]
286
321
  Sequel.synchronize{@transactions.delete(conn)}
287
- if callbacks
288
- callbacks.each(&:call)
289
- end
290
322
  end
323
+
324
+ callbacks.each(&:call) if callbacks
291
325
  end
292
326
 
293
327
  # SQL to rollback to a savepoint
@@ -719,31 +719,33 @@ module Sequel
719
719
  # DB[:table].to_hash([:id, :name]) # SELECT * FROM table
720
720
  # # {[1, 'Jim']=>{:id=>1, :name=>'Jim'}, [2, 'Bob'=>{:id=>2, :name=>'Bob'}, ...}
721
721
  #
722
- # This method accepts an optional :hash parameter (which can be a hash with
723
- # a default value, a hash with a default proc, or any object that supports
724
- # #[] and #[]=) into which entries will be merged. The default behavior is
725
- # to start with a new, empty hash.
722
+ # Options:
723
+ # :all :: Use all instead of each to retrieve the objects
724
+ # :hash :: The object into which the values will be placed. If this is not
725
+ # given, an empty hash is used. This can be used to use a hash with
726
+ # a default value or default proc.
726
727
  def to_hash(key_column, value_column = nil, opts = OPTS)
727
728
  h = opts[:hash] || {}
729
+ meth = opts[:all] ? :all : :each
728
730
  if value_column
729
731
  return naked.to_hash(key_column, value_column, opts) if row_proc
730
732
  if value_column.is_a?(Array)
731
733
  if key_column.is_a?(Array)
732
- each{|r| h[r.values_at(*key_column)] = r.values_at(*value_column)}
734
+ send(meth){|r| h[r.values_at(*key_column)] = r.values_at(*value_column)}
733
735
  else
734
- each{|r| h[r[key_column]] = r.values_at(*value_column)}
736
+ send(meth){|r| h[r[key_column]] = r.values_at(*value_column)}
735
737
  end
736
738
  else
737
739
  if key_column.is_a?(Array)
738
- each{|r| h[r.values_at(*key_column)] = r[value_column]}
740
+ send(meth){|r| h[r.values_at(*key_column)] = r[value_column]}
739
741
  else
740
- each{|r| h[r[key_column]] = r[value_column]}
742
+ send(meth){|r| h[r[key_column]] = r[value_column]}
741
743
  end
742
744
  end
743
745
  elsif key_column.is_a?(Array)
744
- each{|r| h[key_column.map{|k| r[k]}] = r}
746
+ send(meth){|r| h[key_column.map{|k| r[k]}] = r}
745
747
  else
746
- each{|r| h[r[key_column]] = r}
748
+ send(meth){|r| h[r[key_column]] = r}
747
749
  end
748
750
  h
749
751
  end
@@ -767,31 +769,34 @@ module Sequel
767
769
  # DB[:table].to_hash_groups([:first, :middle]) # SELECT * FROM table
768
770
  # # {['Jim', 'Bob']=>[{:id=>1, :first=>'Jim', :middle=>'Bob', :last=>'Smith'}, ...], ...}
769
771
  #
770
- # This method accepts an optional :hash parameter (which can be a hash with
771
- # a default value, a hash with a default proc, or any object that supports
772
- # #[] and #[]=) into which entries will be merged. The default behavior is
772
+ # Options:
773
+ # :all :: Use all instead of each to retrieve the objects
774
+ # :hash :: The object into which the values will be placed. If this is not
775
+ # given, an empty hash is used. This can be used to use a hash with
776
+ # a default value or default proc.
773
777
  # to start with a new, empty hash.
774
778
  def to_hash_groups(key_column, value_column = nil, opts = OPTS)
775
779
  h = opts[:hash] || {}
780
+ meth = opts[:all] ? :all : :each
776
781
  if value_column
777
782
  return naked.to_hash_groups(key_column, value_column, opts) if row_proc
778
783
  if value_column.is_a?(Array)
779
784
  if key_column.is_a?(Array)
780
- each{|r| (h[r.values_at(*key_column)] ||= []) << r.values_at(*value_column)}
785
+ send(meth){|r| (h[r.values_at(*key_column)] ||= []) << r.values_at(*value_column)}
781
786
  else
782
- each{|r| (h[r[key_column]] ||= []) << r.values_at(*value_column)}
787
+ send(meth){|r| (h[r[key_column]] ||= []) << r.values_at(*value_column)}
783
788
  end
784
789
  else
785
790
  if key_column.is_a?(Array)
786
- each{|r| (h[r.values_at(*key_column)] ||= []) << r[value_column]}
791
+ send(meth){|r| (h[r.values_at(*key_column)] ||= []) << r[value_column]}
787
792
  else
788
- each{|r| (h[r[key_column]] ||= []) << r[value_column]}
793
+ send(meth){|r| (h[r[key_column]] ||= []) << r[value_column]}
789
794
  end
790
795
  end
791
796
  elsif key_column.is_a?(Array)
792
- each{|r| (h[key_column.map{|k| r[k]}] ||= []) << r}
797
+ send(meth){|r| (h[key_column.map{|k| r[k]}] ||= []) << r}
793
798
  else
794
- each{|r| (h[r[key_column]] ||= []) << r}
799
+ send(meth){|r| (h[r[key_column]] ||= []) << r}
795
800
  end
796
801
  h
797
802
  end
@@ -157,6 +157,11 @@ module Sequel
157
157
  false
158
158
  end
159
159
 
160
+ # Whether the dataset supports skipping locked rows when returning data.
161
+ def supports_skip_locked?
162
+ false
163
+ end
164
+
160
165
  # Whether the database supports SELECT *, column FROM table
161
166
  def supports_select_all_and_column?
162
167
  true
@@ -827,6 +827,12 @@ module Sequel
827
827
  end
828
828
  end
829
829
 
830
+ # Skip locked rows when returning results from this dataset.
831
+ def skip_locked
832
+ raise(Error, 'This dataset does not support skipping locked rows') unless supports_skip_locked?
833
+ clone(:skip_locked=>true)
834
+ end
835
+
830
836
  # Unbind bound variables from this dataset's filter and return an array of two
831
837
  # objects. The first object is a modified dataset where the filter has been
832
838
  # replaced with one that uses bound variable placeholders. The second object
@@ -63,7 +63,7 @@ module Sequel
63
63
  # Format the value so it takes up exactly size characters
64
64
  def self.format_cell(size, v) # :nodoc:
65
65
  case v
66
- when Bignum, Fixnum
66
+ when Integer
67
67
  "%#{size}d" % v
68
68
  when Float, BigDecimal
69
69
  "%#{size}g" % v
@@ -20,7 +20,7 @@
20
20
  #
21
21
  # This extension may not work correctly in the following cases:
22
22
  #
23
- # * log_yield is not used when executing the query.
23
+ # * log_connection_yield is not used when executing the query.
24
24
  # * The underlying exception is frozen or reused.
25
25
  # * The underlying exception doesn't correctly record instance
26
26
  # variables set on it (seems to happen on JRuby when underlying
@@ -57,12 +57,12 @@ module Sequel
57
57
  # If there are no loggers for this database and an exception is raised
58
58
  # store the SQL related to the exception with the exception, so it
59
59
  # is available for DatabaseError#sql later.
60
- def log_yield(sql, args=nil)
60
+ def log_connection_yield(sql, conn, args=nil)
61
61
  if @loggers.empty?
62
62
  begin
63
63
  yield
64
64
  rescue => e
65
- sql = "#{sql}; #{args.inspect}" if args
65
+ sql = "#{connection_info(conn) if conn && log_connection_info}#{sql}#{"; #{args.inspect}" if args}"
66
66
  e.instance_variable_set(:@sequel_error_sql, sql)
67
67
  raise
68
68
  end
@@ -405,11 +405,20 @@ module Sequel
405
405
 
406
406
  # Delegate to the ruby range object so that the object mostly acts like a range.
407
407
  range_methods = %w'each last first step'
408
- range_methods << 'cover?' if RUBY_VERSION >= '1.9'
409
408
  range_methods.each do |m|
410
409
  class_eval("def #{m}(*a, &block) to_range.#{m}(*a, &block) end", __FILE__, __LINE__)
411
410
  end
412
411
 
412
+ # Return whether the value is inside the range.
413
+ def cover?(value)
414
+ return false if empty?
415
+ b = self.begin
416
+ return false if b && b.send(exclude_begin? ? :>= : :>, value)
417
+ e = self.end
418
+ return false if e && e.send(exclude_end? ? :<= : :<, value)
419
+ true
420
+ end
421
+
413
422
  # Consider the receiver equal to other PGRange instances with the
414
423
  # same beginning, ending, exclusions, and database type. Also consider
415
424
  # it equal to Range instances if this PGRange can be converted to a
@@ -25,17 +25,17 @@ module Sequel
25
25
  if !$1 && $2 && $2.to_i >= 10 && $3
26
26
  # Unsigned integer type with 10 digits can potentially contain values which
27
27
  # don't fit signed integer type, so use bigint type in target database.
28
- {:type=>Bignum}
28
+ {:type=>:Bignum}
29
29
  else
30
30
  {:type=>Integer}
31
31
  end
32
32
  when /\Atinyint(?:\((\d+)\))?(?: unsigned)?\z/o
33
33
  {:type =>schema[:type] == :boolean ? TrueClass : Integer}
34
34
  when /\Abigint(?:\((?:\d+)\))?(?: unsigned)?\z/o
35
- {:type=>Bignum}
35
+ {:type=>:Bignum}
36
36
  when /\A(?:real|float|double(?: precision)?|double\(\d+,\d+\)(?: unsigned)?)\z/o
37
37
  {:type=>Float}
38
- when 'boolean', 'bit'
38
+ when 'boolean', 'bit', 'bool'
39
39
  {:type=>TrueClass}
40
40
  when /\A(?:(?:tiny|medium|long|n)?text|clob)\z/o
41
41
  {:type=>String, :text=>true}
@@ -206,7 +206,7 @@ END_MIG
206
206
  gen.foreign_key(name, table, col_opts)
207
207
  else
208
208
  gen.column(name, type, col_opts)
209
- if [Integer, Bignum, Float].include?(type) && schema[:db_type] =~ / unsigned\z/io
209
+ if [Integer, :Bignum, Float].include?(type) && schema[:db_type] =~ / unsigned\z/io
210
210
  gen.check(Sequel::SQL::Identifier.new(name) >= 0)
211
211
  end
212
212
  end
@@ -407,8 +407,11 @@ END_MIG
407
407
  else
408
408
  type = c.delete(:type)
409
409
  opts = opts_inspect(c)
410
- if type.is_a?(Class)
410
+ case type
411
+ when Class
411
412
  "#{type.name} #{name.inspect}#{opts}"
413
+ when :Bignum
414
+ "Bignum #{name.inspect}#{opts}"
412
415
  else
413
416
  "column #{name.inspect}, #{type.inspect}#{opts}"
414
417
  end