Module: SchemaPlusPgIndexes::Middleware::Postgresql::Sql::IndexComponents
- Defined in:
- lib/schema_plus_pg_indexes/middleware/postgresql/sql.rb
Instance Method Summary collapse
-
#around(env) {|env| ... } ⇒ Object
SchemaPlusPgIndexes provides the following extra options for PostgreSQL indexes: *
:expression- SQL expression to index.
Instance Method Details
#around(env) {|env| ... } ⇒ Object
SchemaPlusPgIndexes provides the following extra options for PostgreSQL indexes:
-
:expression- SQL expression to index. column_name can be nil or ommitted, in which case :name must be provided -
:operator_class- an operator class name or a hash mapping column name to operator class name -
+:case_sensitive - setting to
falseis a shorthand for :expression => ‘LOWER(column_name)’
The :case_sensitive => false option ties in with Rails built-in support for case-insensitive searching:
validates_uniqueness_of :name, :case_sensitive => false
Since since :case_sensitive => false is implemented by using :expression, this raises an ArgumentError if both are specified simultaneously.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/schema_plus_pg_indexes/middleware/postgresql/sql.rb', line 21 def around(env) = env. column_names = env.column_names table_name = env.table_name connection = env.connection if env.column_names.empty? raise ArgumentError, "No columns and :expression missing from options - cannot create index" unless [:expression] raise ArgumentError, "No columns, and index name not given. Pass :name option" unless [:name] end expression = .delete(:expression) operator_classes = .delete(:operator_class) case_insensitive = (.delete(:case_sensitive) == false) if expression raise ArgumentError, "Cannot specify :case_sensitive => false with an expression. Use LOWER(column_name)" if case_insensitive expression.strip! if m = expression.match(/^using\s+(?<using>\S+)\s*(?<rest>.*)/i) [:using] = m[:using] expression = m[:rest] end if m = expression.match(/^(?<rest>.*)\s+where\s+(?<where>.*)/i) [:where] = m[:where] expression = m[:rest] end end yield env if operator_classes and not operator_classes.is_a? Hash operator_classes = Hash[column_names.map {|name| [name, operator_classes]}] end if operator_classes or case_insensitive option_strings = Hash[column_names.map {|name| [name, '']}] (operator_classes||{}).stringify_keys.each do |column, opclass| option_strings[column] += " #{opclass}" if opclass end option_strings = connection.send :add_index_sort_order, option_strings, column_names, if case_insensitive caseable_columns = connection.columns(table_name).select { |col| [:string, :text].include?(col.type) }.map(&:name) quoted_column_names = column_names.map do |col_name| (caseable_columns.include?(col_name.to_s) ? "LOWER(#{connection.quote_column_name(col_name)})" : connection.quote_column_name(col_name)) + option_strings[col_name] end else quoted_column_names = column_names.map { |col_name| connection.quote_column_name(col_name) + option_strings[col_name] } end env.sql.columns = quoted_column_names.join(', ') end if expression env.sql.columns = (env.sql.columns.split(/ *, */).reject{|col| expression =~ %r{\b#{col.gsub(/['"]/, '')}\b} } + [expression]).join(', ') end end |