Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Revert "Revert "Add index length support for MySQL [#1852 state:resol…

…ved]" (breaks the build)"

This reverts commit eababa3.
  • Loading branch information...
commit 77adb4bc2019e3a5b64ae8678310d176e30834d0 1 parent eababa3
Pratik authored May 09, 2010
10  activerecord/CHANGELOG
... ...
@@ -1,5 +1,15 @@
1 1
 *2.3.6 (pending)*
2 2
 
  3
+* Add index length support for MySQL. #1852 [Emili Parreno, Pratik Naik]
  4
+
  5
+  Example:
  6
+
  7
+    add_index(:accounts, :name, :name => 'by_name', :length => 10)
  8
+    => CREATE INDEX by_name ON accounts(name(10))
  9
+
  10
+    add_index(:accounts, [:name, :surname], :name => 'by_name_surname', :length => {:name => 10, :surname => 15})
  11
+    => CREATE INDEX by_name_surname ON accounts(name(10), surname(15))
  12
+
3 13
 * find_or_create_by_attr(value, ...) works when attr is protected.  #4457 [Santiago Pastorino, Marc-André Lafortune]
4 14
 
5 15
 * JSON supports a custom root option: to_json(:root => 'custom')  #4515 [Jatinder Singh]
2  activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
@@ -256,7 +256,7 @@ def simplified_type(field_type)
256 256
         end
257 257
     end
258 258
 
259  
-    class IndexDefinition < Struct.new(:table, :name, :unique, :columns) #:nodoc:
  259
+    class IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths) #:nodoc:
260 260
     end
261 261
 
262 262
     # Abstract representation of a column definition. Instances of this type
23  activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -246,18 +246,32 @@ def rename_column(table_name, column_name, new_column_name)
246 246
       # name.
247 247
       #
248 248
       # ===== Examples
  249
+      #
249 250
       # ====== Creating a simple index
250 251
       #  add_index(:suppliers, :name)
251 252
       # generates
252 253
       #  CREATE INDEX suppliers_name_index ON suppliers(name)
  254
+      #
253 255
       # ====== Creating a unique index
254 256
       #  add_index(:accounts, [:branch_id, :party_id], :unique => true)
255 257
       # generates
256 258
       #  CREATE UNIQUE INDEX accounts_branch_id_party_id_index ON accounts(branch_id, party_id)
  259
+      #
257 260
       # ====== Creating a named index
258 261
       #  add_index(:accounts, [:branch_id, :party_id], :unique => true, :name => 'by_branch_party')
259 262
       # generates
260 263
       #  CREATE UNIQUE INDEX by_branch_party ON accounts(branch_id, party_id)
  264
+      #
  265
+      # ====== Creating an index with specific key length
  266
+      #  add_index(:accounts, :name, :name => 'by_name', :length => 10)
  267
+      # generates
  268
+      #  CREATE INDEX by_name ON accounts(name(10))
  269
+      #
  270
+      #  add_index(:accounts, [:name, :surname], :name => 'by_name_surname', :length => {:name => 10, :surname => 15})
  271
+      # generates
  272
+      #  CREATE INDEX by_name_surname ON accounts(name(10), surname(15))
  273
+      #
  274
+      # Note: SQLite doesn't support index length
261 275
       def add_index(table_name, column_name, options = {})
262 276
         column_names = Array(column_name)
263 277
         index_name   = index_name(table_name, :column => column_names)
@@ -268,7 +282,9 @@ def add_index(table_name, column_name, options = {})
268 282
         else
269 283
           index_type = options
270 284
         end
271  
-        quoted_column_names = column_names.map { |e| quote_column_name(e) }.join(", ")
  285
+
  286
+        quoted_column_names = quoted_columns_for_index(column_names, options).join(", ")
  287
+
272 288
         execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names})"
273 289
       end
274 290
 
@@ -426,6 +442,11 @@ def remove_timestamps(table_name)
426 442
       end
427 443
 
428 444
       protected
  445
+        # Overridden by the mysql adapter for supporting index lengths
  446
+        def quoted_columns_for_index(column_names, options = {})
  447
+          column_names.map {|name| quote_column_name(name) }
  448
+        end
  449
+
429 450
         def options_include_default?(options)
430 451
           options.include?(:default) && !(options[:null] == false && options[:default].nil?)
431 452
         end
17  activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
@@ -454,10 +454,11 @@ def indexes(table_name, name = nil)#:nodoc:
454 454
           if current_index != row[2]
455 455
             next if row[2] == "PRIMARY" # skip the primary key
456 456
             current_index = row[2]
457  
-            indexes << IndexDefinition.new(row[0], row[2], row[1] == "0", [])
  457
+            indexes << IndexDefinition.new(row[0], row[2], row[1] == "0", [], [])
458 458
           end
459 459
 
460 460
           indexes.last.columns << row[4]
  461
+          indexes.last.lengths << row[7]
461 462
         end
462 463
         result.free
463 464
         indexes
@@ -586,6 +587,20 @@ def limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key)
586 587
         where_sql
587 588
       end
588 589
 
  590
+      protected
  591
+        def quoted_columns_for_index(column_names, options = {})
  592
+          length = options[:length] if options.is_a?(Hash)
  593
+
  594
+          quoted_column_names = case length
  595
+          when Hash
  596
+            column_names.map {|name| length[name] ? "#{quote_column_name(name)}(#{length[name]})" : quote_column_name(name) }
  597
+          when Fixnum
  598
+            column_names.map {|name| "#{quote_column_name(name)}(#{length})"}
  599
+          else
  600
+            column_names.map {|name| quote_column_name(name) }
  601
+          end
  602
+        end
  603
+
589 604
       private
590 605
         def connect
591 606
           encoding = @config[:encoding]
1  activerecord/lib/active_record/schema_dumper.rb
@@ -170,6 +170,7 @@ def indexes(table, stream)
170 170
             statment_parts << index.columns.inspect
171 171
             statment_parts << (':name => ' + index.name.inspect)
172 172
             statment_parts << ':unique => true' if index.unique
  173
+            statment_parts << (':length => ' + Hash[*index.columns.zip(index.lengths).flatten].inspect) if index.lengths.compact.present?
173 174
 
174 175
             '  ' + statment_parts.join(', ')
175 176
           end
17  activerecord/test/cases/active_schema_test_mysql.rb
@@ -15,6 +15,23 @@ def teardown
15 15
     end
16 16
   end
17 17
 
  18
+  def test_add_index
  19
+    expected = "CREATE  INDEX `index_people_on_last_name` ON `people` (`last_name`)"
  20
+    assert_equal expected, add_index(:people, :last_name, :length => nil)
  21
+
  22
+    expected = "CREATE  INDEX `index_people_on_last_name` ON `people` (`last_name`(10))"
  23
+    assert_equal expected, add_index(:people, :last_name, :length => 10)
  24
+
  25
+    expected = "CREATE  INDEX `index_people_on_last_name_and_first_name` ON `people` (`last_name`(15), `first_name`(15))"
  26
+    assert_equal expected, add_index(:people, [:last_name, :first_name], :length => 15)
  27
+
  28
+    expected = "CREATE  INDEX `index_people_on_last_name_and_first_name` ON `people` (`last_name`(15), `first_name`)"
  29
+    assert_equal expected, add_index(:people, [:last_name, :first_name], :length => {:last_name => 15})
  30
+
  31
+    expected = "CREATE  INDEX `index_people_on_last_name_and_first_name` ON `people` (`last_name`(15), `first_name`(10))"
  32
+    assert_equal expected, add_index(:people, [:last_name, :first_name], :length => {:last_name => 15, :first_name => 10})
  33
+  end
  34
+
18 35
   def test_drop_table
19 36
     assert_equal "DROP TABLE `people`", drop_table(:people)
20 37
   end
8  activerecord/test/cases/migration_test.rb
@@ -92,6 +92,14 @@ def test_add_index
92 92
         assert_nothing_raised { Person.connection.remove_index("people", "last_name_and_first_name") }
93 93
         assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
94 94
         assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
  95
+        assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :length => 10) }
  96
+        assert_nothing_raised { Person.connection.remove_index("people", "last_name") }
  97
+        assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :length => {:last_name => 10}) }
  98
+        assert_nothing_raised { Person.connection.remove_index("people", ["last_name"]) }
  99
+        assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :length => 10) }
  100
+        assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
  101
+        assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :length => {:last_name => 10, :first_name => 20}) }
  102
+        assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
95 103
       end
96 104
 
97 105
       # quoting

0 notes on commit 77adb4b

Please sign in to comment.
Something went wrong with that request. Please try again.