Ruby on Rails
OracleAddIndex

While this index name handling fix is designed for Oracle, it should work just as well with other DBs, as long as the table_alias_length is also what you want for the index name max length.


# Oracle limitations workaround
module ActiveRecord::ConnectionAdapters::SchemaStatements
  # Oracle has an ancient limit of 30 characters for identifiers. Eek!
  # Autogenerate index_names that fit in the db-specific limit.
  #
  # TODO: index_name and friends not implemented yet!
  alias :add_index_without_limit :add_index
  alias :index_name_without_limit :index_name

  # TODO: not implemented yet!
  def index_name(table_name, options) #:nodoc:
    index_name = index_name_without_limit table_name, options
  end

  def add_index(table_name, column_name, options = {})
    index_name = "#{table_name}_#{Array(column_name).first}_index" 
    if Hash === options # legacy support, since this param was a string
      index_type = options[:unique] ? "UNIQUE" : nil
      index_name = options[:name] || index_name
    else
      index_type = options
      options = {}
    end

    if index_name.length > table_alias_length
      # Highly questionable hash function :-)
      def myhash(n)
        (n.hash % 0x81bf1000).to_s(36)
      end
      index_name = index_name[0..(table_alias_length-11)] +
        myhash(index_name[(table_alias_length-10)..-1]) + "_idx" 
    end

    options[:unique] = index_type if index_type
    options[:name] = index_name

    # Rails <= 1.1.2 only (Edge already does this!)
    column_name = Array(column_name).map{|name| quote_column_name name}

    add_index_without_limit table_name, column_name, options
  end
end