class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
Patched version: 3.1.3
- Patched methods
-
indexes
-
Constants
- INDEX_COLUMN_EXPRESSION
Regex to find columns used in index statements
- INDEX_WHERE_EXPRESION
Regex to find where clause in index statements
Public Instance Methods
Find column names from index attributes. If the columns are virtual (ie this is an expression index) then it will try to return the functions that represent each column
@param [String] table_name the name of the table @param [Hash] index index attributes @return [Array]
# File lib/core_ext/active_record/connection_adapters/postgresql_adapter.rb, line 76 def find_column_names(table_name, index) columns = Hash[query(<<-SQL, "Columns for index #{index[:name]} on #{table_name}")] SELECT a.attnum, a.attname FROM pg_attribute a WHERE a.attrelid = #{index[:id]} AND a.attnum IN (#{index[:keys].join(",")}) SQL column_names = columns.values_at(*index[:keys]).compact if column_names.empty? definition = index[:definition].sub(INDEX_WHERE_EXPRESION, '') if column_expression = definition.match(INDEX_COLUMN_EXPRESSION)[1] column_names = split_expression(column_expression).map do |functional_name| remove_type(functional_name) end end end column_names end
Find length of index TODO Update lengths once we merge in ActiveRecord
code that supports it. -dresselm 20120305
@param [Hash] index index attributes @return [Array]
# File lib/core_ext/active_record/connection_adapters/postgresql_adapter.rb, line 138 def find_lengths(index) [] end
Find where statement from index definition
@param [Hash] index index attributes @return [String] where statement
# File lib/core_ext/active_record/connection_adapters/postgresql_adapter.rb, line 129 def find_where_statement(index) index[:definition].scan(INDEX_WHERE_EXPRESION).flatten[0] end
Returns an array of indexes for the given table.
Patch 1 reason:¶ ↑
Since {ActiveRecord::SchemaDumper#tables} is patched to process tables with a schema prefix, the {#indexes} method receives table_name as “<schema>.<table>”. This patch allows it to handle table names with a schema prefix.
Patch 1:¶ ↑
Search using provided schema if table_name includes schema name.
Patch 2 reason:¶ ↑
{ActiveRecord::ConnectionAdapters::PostgreSQLAdapter#indexes} is patched to support partial indexes using :where clause.
Patch 2:¶ ↑
Search the postgres indexdef for the where clause and pass the output to the custom {PgPower::ConnectionAdapters::IndexDefinition}
# File lib/core_ext/active_record/connection_adapters/postgresql_adapter.rb, line 31 def indexes(table_name, name = nil) schema, table = Utils.extract_schema_and_table(table_name) schemas = schema ? "ARRAY['#{schema}']" : 'current_schemas(false)' result = query(<<-SQL, name) SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid, am.amname FROM pg_class t INNER JOIN pg_index d ON t.oid = d.indrelid INNER JOIN pg_class i ON d.indexrelid = i.oid INNER JOIN pg_am am ON i.relam = am.oid WHERE i.relkind = 'i' AND d.indisprimary = 'f' AND t.relname = '#{table}' AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = ANY (#{schemas}) ) ORDER BY i.relname SQL result.map do |row| index = { :name => row[0], :unique => row[1] == 't', :keys => row[2].split(" "), :definition => row[3], :id => row[4], :access_method => row[5] } column_names = find_column_names(table_name, index) unless column_names.empty? where = find_where_statement(index) lengths = find_lengths(index) PgPower::ConnectionAdapters::IndexDefinition.new(table_name, index[:name], index[:unique], column_names, lengths, where, index[:access_method]) end end.compact end
Remove type specification from stored Postgres index definitions
@param [String] column_with_type the name of the column with type @return [String]
@example
remove_type("((col)::text") => "col"
# File lib/core_ext/active_record/connection_adapters/postgresql_adapter.rb, line 150 def remove_type(column_with_type) column_with_type.sub(/\((\w+)\)::\w+/, '\1') end
Splits only on commas outside of parens
# File lib/core_ext/active_record/connection_adapters/postgresql_adapter.rb, line 99 def split_expression(expression) result = [] parens = 0 buffer = "" expression.chars do |char| case char when ',' if parens == 0 result.push(buffer) buffer = "" next end when '(' parens += 1 when ')' parens -= 1 end buffer << char end result << buffer unless buffer.empty? result end