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 +4 -4
- data/README.markdown +13 -0
- data/lib/core_ext/active_record/connection_adapters/abstract/schema_statements.rb +34 -10
- data/lib/core_ext/active_record/connection_adapters/postgresql_adapter.rb +30 -3
- data/lib/core_ext/active_record/schema_dumper.rb +7 -1
- data/lib/pg_saurus/connection_adapters/index_definition.rb +1 -1
- data/lib/pg_saurus/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bfdd2685401333873ea9a135aae494ceadae569c
|
4
|
+
data.tar.gz: f9655837b68a589bf27decdf20c2f4601bd71536
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
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(
|
146
|
-
|
147
|
-
|
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
|
-
|
173
|
+
return name, nil
|
150
174
|
end
|
151
175
|
end
|
152
|
-
private :
|
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
|
-
|
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
|
data/lib/pg_saurus/version.rb
CHANGED
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.
|
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:
|
16
|
+
date: 2019-03-14 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: pg
|