diff options
Diffstat (limited to 'config')
-rw-r--r-- | config/initializers/postgresql_opclasses_support.rb | 211 |
1 files changed, 0 insertions, 211 deletions
diff --git a/config/initializers/postgresql_opclasses_support.rb b/config/initializers/postgresql_opclasses_support.rb deleted file mode 100644 index 7e912180820..00000000000 --- a/config/initializers/postgresql_opclasses_support.rb +++ /dev/null @@ -1,211 +0,0 @@ -# rubocop:disable all - -# These changes add support for PostgreSQL operator classes when creating -# indexes and dumping/loading schemas. Taken from Rails pull request -# https://github.com/rails/rails/pull/19090. -# -# License: -# -# Copyright (c) 2004-2016 David Heinemeier Hansson -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -require 'date' -require 'set' -require 'bigdecimal' -require 'bigdecimal/util' - -# As the Struct definition is changed in this PR/patch we have to first remove -# the existing one. -ActiveRecord::ConnectionAdapters.send(:remove_const, :IndexDefinition) - -module ActiveRecord - module ConnectionAdapters #:nodoc: - # 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 - attrs = [:table, :name, :unique, :columns, :lengths, :orders, :where, :type, :using, :comment, :opclasses] - - class IndexDefinition < Struct.new(*attrs) #:nodoc: - end - end -end - - -module ActiveRecord - module ConnectionAdapters # :nodoc: - module SchemaStatements - def add_index_options(table_name, column_name, options = {}) #:nodoc: - 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, :opclasses) - - index_type = options[:unique] ? "UNIQUE" : "" - index_type = options[:type].to_s if options.key?(:type) - index_name = options[:name].to_s if options.key?(:name) - max_index_length = options.fetch(:internal, false) ? index_name_length : allowed_index_name_length - - if options.key?(:algorithm) - algorithm = index_algorithms.fetch(options[:algorithm]) { - raise ArgumentError.new("Algorithm must be one of the following: #{index_algorithms.keys.map(&:inspect).join(', ')}") - } - end - - using = "USING #{options[:using]}" if options[:using].present? - - if supports_partial_index? - index_options = options[:where] ? " WHERE #{options[:where]}" : "" - end - - if index_name.length > max_index_length - raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' is too long; the limit is #{max_index_length} characters" - end - if data_source_exists?(table_name) && index_name_exists?(table_name, index_name) - raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists" - end - index_columns = quoted_columns_for_index(column_names, options).join(", ") - - [index_name, index_type, index_columns, index_options, algorithm, using] - end - end - end -end - -module ActiveRecord - module ConnectionAdapters - module PostgreSQL - module SchemaStatements - # Returns an array of indexes for the given table. - def indexes(table_name, name = nil) - result = query(<<-SQL, 'SCHEMA') - SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid - FROM pg_class t - INNER JOIN pg_index d ON t.oid = d.indrelid - INNER JOIN pg_class i ON d.indexrelid = i.oid - WHERE i.relkind = 'i' - AND d.indisprimary = 'f' - AND t.relname = '#{table_name}' - AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = ANY (current_schemas(false)) ) - ORDER BY i.relname - SQL - - result.map do |row| - index_name = row[0] - unique = row[1] - indkey = row[2].split(" ").map(&:to_i) - inddef = row[3] - oid = row[4] - - columns = Hash[query(<<-SQL, "SCHEMA")] - SELECT a.attnum, a.attname - FROM pg_attribute a - WHERE a.attrelid = #{oid} - AND a.attnum IN (#{indkey.join(",")}) - SQL - - column_names = columns.values_at(*indkey).compact - - unless column_names.empty? - # add info on sort order for columns (only desc order is explicitly specified, asc is the default) - desc_order_columns = inddef.scan(/(\w+) DESC/).flatten - 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 - opclasses = Hash[inddef.scan(/\((.+?)\)(?:$| WHERE )/).flatten[0].split(',').map do |column_and_opclass| - column, opclass = column_and_opclass.split(' ').map(&:strip) - end.reject do |column, opclass| - ['desc', 'asc'].include?(opclass&.downcase) - end.map do |column, opclass| - [column, opclass] if opclass - end.compact] - - index_attrs = [table_name, index_name, unique, column_names, [], orders, where, nil, using, nil, opclasses] - - IndexDefinition.new(*index_attrs) - end - end.compact - end - - def add_index(table_name, column_name, options = {}) #:nodoc: - index_name, index_type, index_columns_and_opclasses, 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_and_opclasses})#{index_options}" - end - - protected - - def quoted_columns_for_index(column_names, options = {}) - column_opclasses = options[:opclasses] || {} - column_names.map {|name| "#{quote_column_name(name)} #{column_opclasses[name]}"} - - quoted_columns = Hash[column_names.map { |name| [name.to_sym, "#{quote_column_name(name)} #{column_opclasses[name]}"] }] - add_options_for_index_columns(quoted_columns, options).values - end - end - end - end -end - -module ActiveRecord - class SchemaDumper - private - - def indexes(table, stream) - if (indexes = @connection.indexes(table)).any? - add_index_statements = indexes.map do |index| - table_name = remove_prefix_and_suffix(index.table).inspect - " add_index #{([table_name]+index_parts(index)).join(', ')}" - end - - stream.puts add_index_statements.sort.join("\n") - stream.puts - end - end - - def indexes_in_create(table, stream) - if (indexes = @connection.indexes(table)).any? - index_statements = indexes.map do |index| - " t.index #{index_parts(index).join(', ')}" - end - stream.puts index_statements.sort.join("\n") - end - end - - def index_parts(index) - index_parts = [ - index.columns.inspect, - "name: #{index.name.inspect}", - ] - index_parts << "unique: true" if index.unique - index_parts << "length: { #{format_options(index.lengths)} }" if index.lengths.present? - index_parts << "order: { #{format_options(index.orders)} }" if index.orders.present? - index_parts << "where: #{index.where.inspect}" if index.where - index_parts << "using: #{index.using.inspect}" if index.using - index_parts << "type: #{index.type.inspect}" if index.type - index_parts << "opclasses: #{index.opclasses.inspect}" if index.opclasses.present? - index_parts << "comment: #{index.comment.inspect}" if index.comment - index_parts - end - - def format_options(options) - options.map { |key, value| "#{key}: #{value.inspect}" }.join(", ") - end - end -end |