pg_saurus 3.3.0 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 95526ab7651625ecb8d454074e855cbddb574524
4
- data.tar.gz: a44975a7e86b74893dbec2ded843a2a82b80780c
3
+ metadata.gz: bfdd2685401333873ea9a135aae494ceadae569c
4
+ data.tar.gz: f9655837b68a589bf27decdf20c2f4601bd71536
5
5
  SHA512:
6
- metadata.gz: edde7148883c2b70be2f90ec6894fd4cabb644c6e981af6a224c8842ab9f6b221e2a4e4c624f396d4f54b0249d09fbd2eee79666fd2e815fbdb1d78f910e773b
7
- data.tar.gz: ab9d11096b351eb872a7c8a16e5569ccce00a657863a4293987d34a5f844c3c19f9df540f2b7466a3a07544d172ed2f5a9299e9ce83a4ee3b3e62f54a14322c5
6
+ metadata.gz: 56a742d9ee24d6c27e5057aa87a9fb9034670e0e577a8ef66128850a489321019d0e5016ad0160f54a2e01dc3c8be66f992dc692d94e6d8c0f8734c6be250ed5
7
+ data.tar.gz: 4c047507f0762b571c64aec2a85a000d779bab42f98aed65652fe2e918f5f25291ea5cf62f0aa3a918d04cf5557958432281cfdae8e477247bf15f3dc97f3eea
data/README.markdown CHANGED
@@ -11,6 +11,7 @@ An ActiveRecord extension to get more from PostgreSQL:
11
11
  * [Enhancements to the Rails 4.2 foreign key support](#foreign-keys).
12
12
  * Use [partial indexes](#partial-indexes).
13
13
  * Use [indexes on expressions](#indexes-on-expressions).
14
+ * Use [indexes with custom ops classes](#indexes-with-operator-classes).
14
15
  * [Run index creation concurrently](#concurrent-index-creation).
15
16
  * Create/drop [views](#views).
16
17
  * Create/drop [functions](#functions).
@@ -241,6 +242,18 @@ create_extension 'fuzzystrmatch'
241
242
  add_index(:comments, 'dmetaphone(author)', using: 'gist')
242
243
  ```
243
244
 
245
+ ## Indexes with operator classes
246
+
247
+ Specifying an [operator class on each column of an index](https://www.postgresql.org/docs/10/indexes-opclass.html) is supported.
248
+
249
+ ### Examples
250
+
251
+ Add an index with a custom ops class:
252
+
253
+ ```ruby
254
+ add_index(:books, "title varchar_pattern_ops")
255
+ ```
256
+
244
257
  ## Concurrent index creation
245
258
 
246
259
  PostgreSQL supports concurrent index creation. PgSaurus supports that feature by adding support
@@ -5,6 +5,8 @@ module ActiveRecord
5
5
  # function call
6
6
  FUNCTIONAL_INDEX_REGEXP = /(\w+)\(((?:'.+'(?:::\w+)?, *)*)(\w+)\)/
7
7
 
8
+ # Regexp used to find the operator name
9
+ OPERATOR_REGEXP = /(.+)\s(\w+)$/
8
10
 
9
11
  # Redefine original add_index method to handle :concurrently option.
10
12
  #
@@ -132,24 +134,46 @@ module ActiveRecord
132
134
  # Override super method to provide support for expression column names.
133
135
  def quoted_columns_for_index(column_names, options = {})
134
136
  column_names.map do |name|
135
- if name =~ FUNCTIONAL_INDEX_REGEXP
136
- "#{$1}(#{$2}#{quote_column_name($3)})"
137
- else
138
- quote_column_name(name)
139
- end
137
+ column_name, operator_name = split_column_name(name)
138
+
139
+ result_name = if column_name =~ FUNCTIONAL_INDEX_REGEXP
140
+ "#{$1}(#{$2}#{quote_column_name($3)})"
141
+ else
142
+ quote_column_name(column_name)
143
+ end
144
+
145
+ result_name += " " + operator_name if operator_name
146
+
147
+ result_name
140
148
  end
141
149
  end
142
150
  protected :quoted_columns_for_index
143
151
 
144
152
  # Map an expression to a name appropriate for an index.
145
- def expression_index_name(column_name)
146
- if column_name =~ FUNCTIONAL_INDEX_REGEXP
147
- "#{$1.downcase}_#{$3}"
153
+ def expression_index_name(name)
154
+ column_name, operator_name = split_column_name(name)
155
+
156
+ result_name = if column_name =~ FUNCTIONAL_INDEX_REGEXP
157
+ "#{$1.downcase}_#{$3}"
158
+ else
159
+ column_name
160
+ end
161
+
162
+ result_name += "_" + operator_name if operator_name
163
+
164
+ result_name
165
+ end
166
+ private :expression_index_name
167
+
168
+ # Split column name to name and operator class if possible.
169
+ def split_column_name(name)
170
+ if name =~ OPERATOR_REGEXP
171
+ return $1, $2
148
172
  else
149
- column_name
173
+ return name, nil
150
174
  end
151
175
  end
152
- private :expression_index_name
176
+ private :split_column_name
153
177
  end
154
178
  end
155
179
  end
@@ -71,7 +71,7 @@ module ActiveRecord # :nodoc:
71
71
  schemas = schema ? "ARRAY['#{schema}']" : 'current_schemas(false)'
72
72
 
73
73
  result = query(<<-SQL, name)
74
- SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid, am.amname
74
+ SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid, am.amname, d.indclass
75
75
  FROM pg_class t
76
76
  INNER JOIN pg_index d ON t.oid = d.indrelid
77
77
  INNER JOIN pg_class i ON d.indexrelid = i.oid
@@ -90,11 +90,14 @@ module ActiveRecord # :nodoc:
90
90
  :keys => row[2].split(" "),
91
91
  :definition => row[3],
92
92
  :id => row[4],
93
- :access_method => row[5]
93
+ :access_method => row[5],
94
+ :operators => row[6].split(" ")
94
95
  }
95
96
 
96
97
  column_names = find_column_names(table_name, index)
97
98
 
99
+ operator_names = find_operator_names(column_names, index)
100
+
98
101
  unless column_names.empty?
99
102
  where = find_where_statement(index)
100
103
  lengths = find_lengths(index)
@@ -106,7 +109,8 @@ module ActiveRecord # :nodoc:
106
109
  column_names,
107
110
  lengths,
108
111
  where,
109
- index[:access_method]
112
+ index[:access_method],
113
+ operator_names
110
114
  )
111
115
  end
112
116
  end.compact
@@ -141,6 +145,29 @@ module ActiveRecord # :nodoc:
141
145
  column_names
142
146
  end
143
147
 
148
+ # Find non-default operator class names for columns from index.
149
+ #
150
+ # @param column_names [Array] List of columns from index.
151
+ # @param index [Hash] index index attributes
152
+ # @return [Hash]
153
+ def find_operator_names(column_names, index)
154
+ column_names.each_with_index.inject({}) do |class_names, (column_name, column_index)|
155
+ result = query(<<-SQL, "Classes for columns for index #{index[:name]} for column #{column_name}")
156
+ SELECT op.opcname, op.opcdefault
157
+ FROM pg_opclass op
158
+ WHERE op.oid = #{index[:operators][column_index]};
159
+ SQL
160
+
161
+ row = result.first
162
+
163
+ if row && row[1] == "f"
164
+ class_names[column_name] = row[0]
165
+ end
166
+
167
+ class_names
168
+ end
169
+ end
170
+
144
171
  # Splits only on commas outside of parens
145
172
  def split_expression(expression)
146
173
  result = []
@@ -15,9 +15,15 @@ module ActiveRecord #:nodoc:
15
15
  def indexes(table, stream)
16
16
  if (indexes = @connection.indexes(table)).any?
17
17
  add_index_statements = indexes.map do |index|
18
+ columns = index.columns.map do |column_name|
19
+ column_name += ' ' +index.operators[column_name] if index.operators.key?(column_name)
20
+
21
+ column_name
22
+ end
23
+
18
24
  statement_parts = [
19
25
  ('add_index ' + index.table.inspect),
20
- index.columns.inspect,
26
+ columns.inspect,
21
27
  (':name => ' + index.name.inspect),
22
28
  ]
23
29
  statement_parts << ':unique => true' if index.unique
@@ -3,6 +3,6 @@ module PgSaurus::ConnectionAdapters
3
3
  # Overrides ActiveRecord::ConnectionAdapters::IndexDefinition
4
4
  # with the additional :where parameter.
5
5
  class IndexDefinition < Struct.new( :table, :name, :unique, :columns,
6
- :lengths, :where, :access_method )
6
+ :lengths, :where, :access_method, :operators )
7
7
  end
8
8
  end
@@ -1,4 +1,4 @@
1
1
  module PgSaurus
2
2
  # Version of pg_saurus gem.
3
- VERSION = "3.3.0"
3
+ VERSION = "3.4.0"
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_saurus
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.0
4
+ version: 3.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Potapov Sergey
@@ -13,7 +13,7 @@ authors:
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
- date: 2018-09-06 00:00:00.000000000 Z
16
+ date: 2019-03-14 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: pg