Ticket #4353: bigint_support_in_migrations.3.diff
| File bigint_support_in_migrations.3.diff, 11.9 kB (added by shammond@northpub.com, 2 years ago) |
|---|
-
test/migration_test.rb
old new 72 72 Person.connection.drop_table :testings rescue nil 73 73 end 74 74 75 def test_create_table_with_big_id 76 Person.connection.create_table :testings, :use_big_id => true do |t| 77 t.column :name, :string 78 end 79 80 columns = Person.connection.columns(:testings) 81 assert columns.find { |c| c.name == 'id' and c.type == :integer and c.limit == 8} if current_adapter?(:MysqlAdapter) 82 assert columns.find { |c| c.name == 'id' and c.type == :integer and c.limit == 8} if current_adapter?(:SqliteAdapter) 83 ensure 84 Person.connection.drop_table :testings rescue nil 85 end 86 75 87 def test_create_table_with_not_null_column 76 88 Person.connection.create_table :testings do |t| 77 89 t.column :foo, :string, :null => false … … 178 190 assert_equal TrueClass, bob.male?.class 179 191 end 180 192 193 def test_integer_limits 194 Person.delete_all 195 Person.connection.add_column 'people', 'tiny', :integer, :limit => 1 196 Person.connection.add_column 'people', 'small', :integer, :limit => 2 197 Person.connection.add_column 'people', 'medium', :integer, :limit => 3 198 Person.connection.add_column 'people', 'normal', :integer, :limit => 4 199 Person.connection.add_column 'people', 'five_bytes', :integer, :limit => 5 200 Person.connection.add_column 'people', 'big', :integer, :limit => 8 201 Person.connection.add_column 'people', 'ten_bytes', :integer, :limit => 10 202 Person.connection.add_column 'people', 'short_string', :string, :limit => 9 203 204 assert_nothing_raised { Person.create :tiny => 123, :small => 1234, 205 :medium => 123456, :normal => 123456789, :five_bytes => 123456789123, 206 :big => 123456789123456789, :ten_bytes => 1208925819614629174706176, 207 :short_string => '123456789'} 208 bob = Person.find(:first) 209 210 assert_equal 123, bob.tiny 211 assert_equal 1234, bob.small 212 assert_equal 123456, bob.medium 213 assert_equal 123456789, bob.normal 214 assert_equal 123456789123, bob.five_bytes 215 assert_equal 123456789123456789, bob.big 216 # number too big for mysql and should be truncated 217 assert_not_equal 1208925819614629174706176, bob.ten_bytes if current_adapter?(:MysqlAdapter) 218 assert_equal '123456789', bob.short_string 219 220 if current_adapter?(:MysqlAdapter) 221 person_columns = Person.columns_hash 222 assert_equal 1, person_columns['tiny'].limit 223 assert_equal 2, person_columns['small'].limit 224 assert_equal 3, person_columns['medium'].limit 225 assert_equal 4, person_columns['normal'].limit 226 assert_equal 8, person_columns['five_bytes'].limit # no five-byte type in mysql, use 8-bytes 227 assert_equal 8, person_columns['big'].limit 228 assert_equal 8, person_columns['ten_bytes'].limit 229 assert_equal 9, person_columns['short_string'].limit 230 end 231 end 232 181 233 def test_add_remove_single_field_using_string_arguments 182 234 assert !Person.column_methods_hash.include?(:last_name) 183 235 … … 282 334 new_columns = Person.connection.columns(Person.table_name, "#{name} Columns") 283 335 assert_nil new_columns.find { |c| c.name == 'age' and c.type == :integer } 284 336 assert new_columns.find { |c| c.name == 'age' and c.type == :string } 285 end 337 end 286 338 287 339 def test_change_column_with_new_default 288 340 Person.connection.add_column "people", "administrator", :boolean, :default => 1 … … 294 346 assert !Person.new.administrator? 295 347 end 296 348 349 def test_change_integer_column_limits 350 Person.connection.add_column 'people', 'weight', :integer, :limit => 2 351 Person.connection.add_column 'people', 'age', :integer, :limit => 4 352 353 old_columns = Person.connection.columns(Person.table_name, "#{name} Columns") 354 assert old_columns.find { |c| c.name == 'weight' and c.type == :integer and c.limit == 2} 355 assert old_columns.find { |c| c.name == 'age' and c.type == :integer and c.limit == 4} 356 357 assert_nothing_raised { Person.connection.change_column 'people', 'weight', :integer, :limit => 4 } 358 assert_nothing_raised { Person.connection.change_column 'people', 'age', :integer, :limit => 8 } 359 360 new_columns = Person.connection.columns(Person.table_name, "#{name} Columns") 361 assert_nil new_columns.find { |c| c.name == 'weight' and c.type == :integer and c.limit == 2} 362 assert_nil new_columns.find { |c| c.name == 'age' and c.type == :integer and c.limit == 4} 363 assert new_columns.find { |c| c.name == 'weight' and c.type == :integer and c.limit == 4 } 364 assert new_columns.find { |c| c.name == 'age' and c.type == :integer and c.limit == 8 } 365 end 366 297 367 def test_add_table 298 368 assert !Reminder.table_exists? 299 369 -
lib/active_record/connection_adapters/abstract/schema_statements.rb
old new 45 45 # The +options+ hash can include the following keys: 46 46 # [<tt>:id</tt>] 47 47 # Set to true or false to add/not add a primary key column 48 # automatically. Defaults to true. 48 # [<tt>:use_big_id</tt>] 49 # Set to true or false to use the largest supported integer type as the 50 # primary key column. Defaults to false. 49 51 # [<tt>:primary_key</tt>] 50 52 # The name of the primary key, if one is to be added automatically. 51 53 # Defaults to +id+. … … 75 77 # name varchar(80) 76 78 # ) 77 79 # 80 # ====== Use the largest integer type supported as the primary key column 81 # create_table(:objects, :use_big_id => true) do |t| 82 # t.column :name, :string, :limit => 80 83 # end 84 # generates (in MySQL): 85 # CREATE TABLE objects ( 86 # id bigint(21) UNSIGNED DEFAULT NULL auto_increment PRIMARY KEY, 87 # name varchar(80) 88 # ) 89 # 78 90 # ====== Do not add a primary key column 79 91 # create_table(:categories_suppliers, :id => false) do |t| 80 92 # t.column :category_id, :integer … … 89 101 # See also TableDefinition#column for details on how to create columns. 90 102 def create_table(name, options = {}) 91 103 table_definition = TableDefinition.new(self) 92 table_definition.primary_key(options[:primary_key] || "id" ) unless options[:id] == false104 table_definition.primary_key(options[:primary_key] || "id", options[:use_big_id] || false) unless options[:id] == false 93 105 94 106 yield table_definition 95 107 … … 254 266 255 267 256 268 def type_to_sql(type, limit = nil) #:nodoc: 257 native = native_database_types[type] 269 unless self.class.method_defined? :native_database_type 270 native = native_database_types[type] 271 else 272 # If database defines unusual type and/or limits (like MySQL's integer types) 273 # define a method native_database_type and return the correct type 274 # and limit 275 native = native_database_type(type, limit) 276 limit = nil # native_database_type is responsible for returning the correct limit 277 end 258 278 limit ||= native[:limit] 259 279 column_type_sql = native[:name] 260 280 column_type_sql << "(#{limit})" if limit -
lib/active_record/connection_adapters/abstract/schema_definitions.rb
old new 194 194 195 195 # Appends a primary key definition to the table definition. 196 196 # Can be called multiple times, but this is probably not a good idea. 197 def primary_key(name) 198 column(name, native[:primary_key]) 197 def primary_key(name, use_big_id = false) 198 key_type = ( use_big_id && !native[:big_primary_key].nil? ) ? :big_primary_key : :primary_key 199 column(name, native[key_type]) 199 200 end 200 201 201 202 # Returns a ColumnDefinition for the column with name +name+. … … 212 213 # 213 214 # Available options are (none of these exists by default): 214 215 # * <tt>:limit</tt>: 215 # Requests a maximum column length (<tt>:string</tt>, <tt>:text</tt>, 216 # <tt>:binary</tt> or <tt>:integer</tt> columns only) 216 # Requests a maximum column length in bytes (<tt>:string</tt>, <tt>:text</tt>, 217 # <tt>:binary</tt> or <tt>:integer</tt> columns only). In MySQL this option 218 # determines the integer type that will be used, so <tt>:limit => 8</tt> 219 # will produce a column of type <tt>bigint</tt> and <tt>:limit => 3</tt> 220 # will produce a column of type <tt>mediumint</tt>. 217 221 # * <tt>:default</tt>: 218 222 # The column's default value. You cannot explicitely set the default 219 223 # value to +NULL+. Simply leave off this option if you want a +NULL+ -
lib/active_record/connection_adapters/mysql_adapter.rb
old new 46 46 return :string if field_type =~ /enum/i 47 47 super 48 48 end 49 50 def extract_limit(sql_type) 51 case sql_type 52 when /tinyint/ then return 1 53 when /smallint/ then return 2 54 when /mediumint/ then return 3 55 when /bigint/ then return 8 56 when /int/ then return 4 57 end 58 super 59 end 49 60 end 50 61 51 62 # The MySQL adapter will work with both Ruby/MySQL, which is a Ruby-based MySQL adapter that comes bundled with Active Record, and with … … 99 110 def native_database_types #:nodoc 100 111 { 101 112 :primary_key => "int(11) DEFAULT NULL auto_increment PRIMARY KEY", 113 :big_primary_key => "bigint(21) UNSIGNED DEFAULT NULL auto_increment PRIMARY KEY", 102 114 :string => { :name => "varchar", :limit => 255 }, 103 115 :text => { :name => "text" }, 116 :tinyint => { :name => "tinyint", :limit => 4 }, 117 :smallint => { :name => "smallint", :limit => 6 }, 118 :mediumint => { :name => "mediumint", :limit => 9 }, 104 119 :integer => { :name => "int", :limit => 11 }, 120 :bigint => { :name => "bigint", :limit => 21 }, 105 121 :float => { :name => "float" }, 106 122 :datetime => { :name => "datetime" }, 107 123 :timestamp => { :name => "datetime" }, … … 112 128 } 113 129 end 114 130 131 def native_database_type(type, limit=nil) 132 mysql_integer_types = %w{tinyint smallint mediumint int bigint} 133 if type == :integer 134 native_type = case limit 135 when nil then native_database_types[:integer] 136 when 1 then native_database_types[:tinyint] 137 when 2 then native_database_types[:smallint] 138 when 3 then native_database_types[:mediumint] 139 when 4 then native_database_types[:integer] 140 else native_database_types[:bigint] 141 end 142 else native_type = native_database_types[type] 143 end 144 type_with_correct_limit = native_type.clone # make a copy so we can change the limit 145 type_with_correct_limit[:limit] = limit unless limit.nil? or mysql_integer_types.include? type_with_correct_limit[:name] 115 146 147 type_with_correct_limit 148 end 149 116 150 # QUOTING ================================================== 117 151 118 152 def quote(value, column = nil)