Skip to content

Instantly share code, notes, and snippets.

@felixbuenemann
Created July 11, 2014 00:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save felixbuenemann/f011b0e883a983f00d06 to your computer and use it in GitHub Desktop.
Save felixbuenemann/f011b0e883a983f00d06 to your computer and use it in GitHub Desktop.
diff -ur activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
--- activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb 2014-07-11 02:35:32.000000000 +0200
+++ activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb 2014-07-11 01:31:14.000000000 +0200
@@ -8,7 +8,7 @@
# Abstract representation of an index definition on a table. Instances of
# this type are typically created and returned by methods in database
# adapters. e.g. ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter#indexes
- class IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths, :orders, :where, :type, :using) #:nodoc:
+ class IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths, :orders, :where, :type, :using, :opclass) #:nodoc:
end
# Abstract representation of a column definition. Instances of this type
diff -ur activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
--- activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb 2014-07-11 02:35:32.000000000 +0200
+++ activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb 2014-07-11 02:25:23.000000000 +0200
@@ -774,7 +774,7 @@
column_names = Array(column_name)
index_name = index_name(table_name, column: column_names)
- options.assert_valid_keys(:unique, :order, :name, :where, :length, :internal, :using, :algorithm, :type)
+ options.assert_valid_keys(:unique, :order, :name, :where, :length, :internal, :using, :algorithm, :type, :opclass)
index_type = options[:unique] ? "UNIQUE" : ""
index_type = options[:type].to_s if options.key?(:type)
@@ -788,6 +788,7 @@
end
using = "USING #{options[:using]}" if options[:using].present?
+ opclass = " #{options[:opclass]}" if options[:using].present? && options[:opclass].present?
if supports_partial_index?
index_options = options[:where] ? " WHERE #{options[:where]}" : ""
@@ -801,7 +802,7 @@
end
index_columns = quoted_columns_for_index(column_names, options).join(", ")
- [index_name, index_type, index_columns, index_options, algorithm, using]
+ [index_name, index_type, index_columns, index_options, algorithm, using, opclass]
end
def index_name_for_remove(table_name, options = {})
diff -ur activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
--- activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb 2014-07-11 02:35:32.000000000 +0200
+++ activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb 2014-07-11 02:22:27.000000000 +0200
@@ -153,6 +153,8 @@
ORDER BY i.relname
SQL
+ valid_opclasses = Regexp.union(opclasses) if result.any?
+
result.map do |row|
index_name = row[0]
unique = row[1] == 't'
@@ -175,12 +177,21 @@
orders = desc_order_columns.any? ? Hash[desc_order_columns.map {|order_column| [order_column, :desc]}] : {}
where = inddef.scan(/WHERE (.+)$/).flatten[0]
using = inddef.scan(/USING (.+?) /).flatten[0].to_sym
+ opclass = inddef.scan(/USING .+? \(.+? (#{valid_opclasses.source})\)/).flatten[0].try(:to_sym)
- IndexDefinition.new(table_name, index_name, unique, column_names, [], orders, where, nil, using)
+ IndexDefinition.new(table_name, index_name, unique, column_names, [], orders, where, nil, using, opclass)
end
end.compact
end
+ # Returns the list of all avalable index opclasses.
+ def opclasses
+ query(<<-SQL, 'SCHEMA').map { |row| row[0] }
+ SELECT opcname
+ FROM pg_opclass
+ SQL
+ end
+
# Returns the list of all column definitions for a table.
def columns(table_name)
# Limit, precision, and scale are all handled by the superclass.
@@ -432,8 +443,8 @@
end
def add_index(table_name, column_name, options = {}) #:nodoc:
- index_name, index_type, index_columns, index_options, index_algorithm, index_using = add_index_options(table_name, column_name, options)
- execute "CREATE #{index_type} INDEX #{index_algorithm} #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} #{index_using} (#{index_columns})#{index_options}"
+ index_name, index_type, index_columns, index_options, index_algorithm, index_using, index_opclass = add_index_options(table_name, column_name, options)
+ execute "CREATE #{index_type} INDEX #{index_algorithm} #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} #{index_using} (#{index_columns}#{index_opclass})#{index_options}"
end
def remove_index!(table_name, index_name) #:nodoc:
diff -ur activerecord/lib/active_record/schema_dumper.rb activerecord/lib/active_record/schema_dumper.rb
--- activerecord/lib/active_record/schema_dumper.rb 2014-07-11 02:35:32.000000000 +0200
+++ activerecord/lib/active_record/schema_dumper.rb 2014-07-11 02:10:11.000000000 +0200
@@ -202,6 +202,8 @@
statement_parts << ('using: ' + index.using.inspect) if index.using
+ statement_parts << ('opclass: ' + index.opclass.inspect) if index.opclass
+
statement_parts << ('type: ' + index.type.inspect) if index.type
' ' + statement_parts.join(', ')
@felixbuenemann
Copy link
Author

These are the minimum required changes to get postgresql index opclass support for migrations and schema dumping. This was supported up to postgres_ext 1.0 with Rails 3.2 with the option index_opclass, but has been removed from the rail 4 versions of the gem.

The patch was created against rails/activerecord 4.1.4.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment