sequel 4.34.0 → 4.35.0

Sign up to get free protection for your applications and to get access to all the features.
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