pg_power 1.6.4 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.markdown +20 -11
- data/lib/core_ext/active_record/connection_adapters/abstract/schema_statements.rb +32 -48
- data/lib/core_ext/active_record/connection_adapters/postgresql_adapter.rb +1 -10
- data/lib/pg_power/connection_adapters/postgresql_adapter.rb +1 -0
- data/lib/pg_power/connection_adapters/postgresql_adapter/extension_methods.rb +12 -8
- data/lib/pg_power/create_index_concurrently.rb +3 -1
- data/lib/pg_power/schema_dumper/extension_methods.rb +1 -1
- data/lib/pg_power/version.rb +1 -1
- metadata +18 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c8b564bc64ebb7c31041272596e103eaad58e60e
|
4
|
+
data.tar.gz: 988c4d9cf044dc4b247e8437658011987efe6a31
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6497ef6e095d1bfe922a57c5ed692feb1bc8e93cf00ac1385ea3a844d442dbde8e9c3da8e0d92ec184547c332980834e40b8df5bafccf7dcb66b74c7d7f8a666
|
7
|
+
data.tar.gz: fe88de2ff07fe6f5969e2f43b75d7ffe03a45d468b2c387a60ac06ebe6d5a5eb786f7ab07a2be2e8c4bea55312f5e79f91076e09b34d2841d40d01bc59ede91b
|
data/README.markdown
CHANGED
@@ -145,7 +145,7 @@ add_foreign_key(:comments, :posts)
|
|
145
145
|
```
|
146
146
|
Does not add an index:
|
147
147
|
```ruby
|
148
|
-
|
148
|
+
add_foreign_key(:comments, :posts, :exclude_index => true)
|
149
149
|
```
|
150
150
|
## Partial Indexes
|
151
151
|
|
@@ -172,15 +172,15 @@ expressions are supported.
|
|
172
172
|
Add an index to a column with a function
|
173
173
|
|
174
174
|
```ruby
|
175
|
-
|
175
|
+
add_index(:comments, "lower(text)")
|
176
176
|
```
|
177
177
|
|
178
178
|
You can also specify index access method
|
179
179
|
|
180
180
|
```ruby
|
181
|
-
|
182
|
-
|
183
|
-
|
181
|
+
create_extension 'btree_gist'
|
182
|
+
create_extension 'fuzzystrmatch'
|
183
|
+
add_index(:comments, 'dmetaphone(author)', :using => 'gist')
|
184
184
|
```
|
185
185
|
|
186
186
|
## Concurrent index creation
|
@@ -193,13 +193,13 @@ DSL on index and foreign keys creation.
|
|
193
193
|
Add an index concurrently to a table
|
194
194
|
|
195
195
|
```ruby
|
196
|
-
|
196
|
+
add_index :table, :column_id, :concurrently => true
|
197
197
|
```
|
198
198
|
|
199
199
|
Add an index concurrently along with foreign key
|
200
200
|
|
201
201
|
```ruby
|
202
|
-
|
202
|
+
add_foreign_key :table1, :table2, :column => :column_id, :concurrent_index => true
|
203
203
|
```
|
204
204
|
|
205
205
|
## Loading/Unloading postgresql extension modules
|
@@ -218,7 +218,7 @@ Load [fuzzystrmatch](http://www.postgresql.org/docs/9.1/static/fuzzystrmatch.htm
|
|
218
218
|
and create its objects in schema *public*:
|
219
219
|
|
220
220
|
```ruby
|
221
|
-
|
221
|
+
create_extension "fuzzystrmatch"
|
222
222
|
```
|
223
223
|
|
224
224
|
|
@@ -226,13 +226,13 @@ Load version *1.0* of the [btree_gist](http://www.postgresql.org/docs/9.1/static
|
|
226
226
|
and create its objects in schema *demography*.
|
227
227
|
|
228
228
|
```ruby
|
229
|
-
|
229
|
+
create_extension "btree_gist", :schema_name => "demography", :version => "1.0"
|
230
230
|
```
|
231
231
|
|
232
232
|
Unload extension module:
|
233
233
|
|
234
234
|
```ruby
|
235
|
-
|
235
|
+
drop_extension "fuzzystrmatch"
|
236
236
|
```
|
237
237
|
|
238
238
|
## Views
|
@@ -243,7 +243,7 @@ that it is preliminary 'alpha' at best.
|
|
243
243
|
### Example
|
244
244
|
|
245
245
|
```ruby
|
246
|
-
|
246
|
+
create_view "demography.citizens_view", "select * from demography.citizens"
|
247
247
|
```
|
248
248
|
|
249
249
|
## Tools
|
@@ -256,6 +256,15 @@ PgPower::Tools.drop_schema "services" # => remove the PG schem
|
|
256
256
|
PgPower::Tools.schemas # => ["public", "information_schema", "nets"]
|
257
257
|
PgPower::Tools.index_exists?(table, columns, options) # => returns true if an index exists for the given params
|
258
258
|
```
|
259
|
+
|
260
|
+
## Rails 3
|
261
|
+
|
262
|
+
If you are using rails 3.x, use previous pg_power version:
|
263
|
+
|
264
|
+
```ruby
|
265
|
+
gem 'pg_power', '~> 1.6.4'
|
266
|
+
```
|
267
|
+
|
259
268
|
## Running tests:
|
260
269
|
|
261
270
|
* Ensure your postgresql has postgres-contrib (Ubuntu) package installed. Tests depend on btree_gist and fuzzystrmatch extensions
|
@@ -5,6 +5,9 @@ module ActiveRecord
|
|
5
5
|
# function call
|
6
6
|
FUNCTIONAL_INDEX_REGEXP = /(\w+)\(((?:'.+'(?:::\w+)?, *)*)(\w+)\)/
|
7
7
|
|
8
|
+
|
9
|
+
# Redefine original add_index method to handle :concurrently option.
|
10
|
+
#
|
8
11
|
# Adds a new index to the table. +column_name+ can be a single Symbol, or
|
9
12
|
# an Array of Symbols.
|
10
13
|
#
|
@@ -19,8 +22,15 @@ module ActiveRecord
|
|
19
22
|
# WHERE
|
20
23
|
# active
|
21
24
|
#
|
22
|
-
def
|
23
|
-
|
25
|
+
def add_index_with_concurrently(table_name, column_name, options = {})
|
26
|
+
creation_method = options.delete(:concurrently) ? 'CONCURRENTLY' : nil
|
27
|
+
|
28
|
+
index_name,
|
29
|
+
index_type,
|
30
|
+
index_columns,
|
31
|
+
index_options,
|
32
|
+
index_algorithm,
|
33
|
+
index_using = add_index_options(table_name, column_name, options)
|
24
34
|
|
25
35
|
# GOTCHA:
|
26
36
|
# It ensures that there is no existing index only for the case when the index
|
@@ -33,22 +43,28 @@ module ActiveRecord
|
|
33
43
|
# indexes. But note that this handles only one of the cases when index
|
34
44
|
# creation can fail!!! All other case should be procesed manually.
|
35
45
|
# -- zekefast 2012-09-25
|
36
|
-
if
|
37
|
-
raise ::PgPower::IndexExistsError,
|
38
|
-
|
46
|
+
if creation_method.present? && index_exists?(table_name, column_name, options)
|
47
|
+
raise ::PgPower::IndexExistsError,
|
48
|
+
"Index #{index_name} for `#{table_name}.#{column_name}` " \
|
49
|
+
"column can not be created concurrently, because such index already exists."
|
39
50
|
end
|
40
51
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
52
|
+
statements = []
|
53
|
+
statements << "CREATE #{index_type} INDEX"
|
54
|
+
statements << creation_method if creation_method.present?
|
55
|
+
statements << index_algorithm if index_algorithm.present?
|
56
|
+
statements << quote_column_name(index_name)
|
57
|
+
statements << "ON"
|
58
|
+
statements << quote_table_name(table_name)
|
59
|
+
statements << index_using if index_using.present?
|
60
|
+
statements << "(#{index_columns})" if index_columns.present?
|
61
|
+
statements << index_options if index_options.present?
|
47
62
|
|
48
|
-
|
63
|
+
sql = statements.join(' ')
|
64
|
+
execute(sql)
|
49
65
|
end
|
50
66
|
|
51
|
-
#
|
67
|
+
# Check to see if an index exists on a table for a given index definition.
|
52
68
|
#
|
53
69
|
# === Examples
|
54
70
|
# # Check that a partial index exists
|
@@ -97,7 +113,7 @@ module ActiveRecord
|
|
97
113
|
end
|
98
114
|
end
|
99
115
|
|
100
|
-
#
|
116
|
+
# Derive the name of the index from the given table name and options hash.
|
101
117
|
def index_name(table_name, options) #:nodoc:
|
102
118
|
if Hash === options # legacy support
|
103
119
|
if options[:column]
|
@@ -113,39 +129,7 @@ module ActiveRecord
|
|
113
129
|
end
|
114
130
|
end
|
115
131
|
|
116
|
-
#
|
117
|
-
#
|
118
|
-
# Added support for partial indexes implemented using the :where option
|
119
|
-
#
|
120
|
-
def add_index_options(table_name, column_name, options = {})
|
121
|
-
column_names = Array(column_name)
|
122
|
-
index_name = index_name(table_name, :column => column_names)
|
123
|
-
index_creation_method = nil
|
124
|
-
|
125
|
-
if Hash === options # legacy support, since this param was a string
|
126
|
-
index_type = options[:unique] ? 'UNIQUE' : ''
|
127
|
-
index_creation_method = options[:concurrently] ? 'CONCURRENTLY' : ''
|
128
|
-
index_name = options[:name].to_s if options.key?(:name)
|
129
|
-
if supports_partial_index?
|
130
|
-
index_options = options[:where] ? " WHERE #{options[:where]}" : ''
|
131
|
-
end
|
132
|
-
else
|
133
|
-
index_type = options
|
134
|
-
end
|
135
|
-
|
136
|
-
if index_name.length > index_name_length
|
137
|
-
raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' is too long; the limit is #{index_name_length} characters"
|
138
|
-
end
|
139
|
-
if index_name_exists?(table_name, index_name, false)
|
140
|
-
raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists"
|
141
|
-
end
|
142
|
-
index_columns = quoted_columns_for_index(column_names, options).join(', ')
|
143
|
-
|
144
|
-
[index_name, index_type, index_creation_method, index_columns, index_options]
|
145
|
-
end
|
146
|
-
protected :add_index_options
|
147
|
-
|
148
|
-
# Override super method to provide support for expression column names
|
132
|
+
# Override super method to provide support for expression column names.
|
149
133
|
def quoted_columns_for_index(column_names, options = {})
|
150
134
|
column_names.map do |name|
|
151
135
|
if name =~ FUNCTIONAL_INDEX_REGEXP
|
@@ -157,7 +141,7 @@ module ActiveRecord
|
|
157
141
|
end
|
158
142
|
protected :quoted_columns_for_index
|
159
143
|
|
160
|
-
# Map an expression to a name appropriate for an index
|
144
|
+
# Map an expression to a name appropriate for an index.
|
161
145
|
def expression_index_name(column_name)
|
162
146
|
if column_name =~ FUNCTIONAL_INDEX_REGEXP
|
163
147
|
"#{$1.downcase}_#{$3}"
|
@@ -4,15 +4,6 @@ module ActiveRecord # :nodoc:
|
|
4
4
|
# Patched methods::
|
5
5
|
# * indexes
|
6
6
|
class PostgreSQLAdapter
|
7
|
-
# In Rails3.2 method #extract_schema_and_table is moved into Utils module.
|
8
|
-
# In Rails3.1 it's implemented right in PostgreSQLAdapter class.
|
9
|
-
# So it's Rails3.2 we include the module into PostgreSQLAdapter in order to make
|
10
|
-
# it compatible to Rails3.1
|
11
|
-
# -- sergey.potapov 2012-06-25
|
12
|
-
if ActiveRecord::VERSION::STRING =~ /^3\.2/
|
13
|
-
include self::Utils
|
14
|
-
end
|
15
|
-
|
16
7
|
# Regex to find columns used in index statements
|
17
8
|
INDEX_COLUMN_EXPRESSION = /ON \w+(?: USING \w+ )?\((.+)\)/
|
18
9
|
# Regex to find where clause in index statements
|
@@ -38,7 +29,7 @@ module ActiveRecord # :nodoc:
|
|
38
29
|
# the custom {PgPower::ConnectionAdapters::IndexDefinition}
|
39
30
|
#
|
40
31
|
def indexes(table_name, name = nil)
|
41
|
-
schema, table = extract_schema_and_table(table_name)
|
32
|
+
schema, table = Utils.extract_schema_and_table(table_name)
|
42
33
|
schemas = schema ? "ARRAY['#{schema}']" : 'current_schemas(false)'
|
43
34
|
|
44
35
|
result = query(<<-SQL, name)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Provides methods to extend {ActiveRecord::ConnectionAdapters::PostgreSQLAdapter}
|
2
2
|
# to support extensions feature.
|
3
3
|
module PgPower::ConnectionAdapters::PostgreSQLAdapter::ExtensionMethods
|
4
|
-
# Default options for {#create_extension} method
|
4
|
+
# Default options for {#create_extension} method.
|
5
5
|
CREATE_EXTENSION_DEFAULTS = {
|
6
6
|
:if_not_exists => true,
|
7
7
|
:schema_name => nil,
|
@@ -9,7 +9,7 @@ module PgPower::ConnectionAdapters::PostgreSQLAdapter::ExtensionMethods
|
|
9
9
|
:old_version => nil
|
10
10
|
}
|
11
11
|
|
12
|
-
# Default options for {#drop_extension} method
|
12
|
+
# Default options for {#drop_extension} method.
|
13
13
|
DROP_EXTENSION_DEFAULTS = {
|
14
14
|
:if_exists => true,
|
15
15
|
:mode => :restrict
|
@@ -29,7 +29,7 @@ module PgPower::ConnectionAdapters::PostgreSQLAdapter::ExtensionMethods
|
|
29
29
|
true
|
30
30
|
end
|
31
31
|
|
32
|
-
#
|
32
|
+
# Execute SQL to load a postgresql extension module into the current database.
|
33
33
|
#
|
34
34
|
# @param [#to_s] extension_name Name of the extension module to load
|
35
35
|
# @param [Hash] options
|
@@ -52,7 +52,7 @@ module PgPower::ConnectionAdapters::PostgreSQLAdapter::ExtensionMethods
|
|
52
52
|
end
|
53
53
|
|
54
54
|
|
55
|
-
#
|
55
|
+
# Execute SQL to remove a postgresql extension module from the current database.
|
56
56
|
#
|
57
57
|
# @param [#to_s] extension_name Name of the extension module to unload
|
58
58
|
# @param [Hash] options
|
@@ -80,7 +80,11 @@ module PgPower::ConnectionAdapters::PostgreSQLAdapter::ExtensionMethods
|
|
80
80
|
execute(sql)
|
81
81
|
end
|
82
82
|
|
83
|
-
#
|
83
|
+
# Query the pg_catalog for all extension modules loaded to the current database.
|
84
|
+
#
|
85
|
+
# @note
|
86
|
+
# Since Rails 4 connection has method +extensions+ that returns array of extensions.
|
87
|
+
# This method is slightly different, since it returns also additional options.
|
84
88
|
#
|
85
89
|
# Please note all extensions which belong to pg_catalog schema are omitted
|
86
90
|
# ===Example
|
@@ -90,7 +94,7 @@ module PgPower::ConnectionAdapters::PostgreSQLAdapter::ExtensionMethods
|
|
90
94
|
# }
|
91
95
|
#
|
92
96
|
# @return [Hash{String => Hash{Symbol => String}}] A list of loaded extensions with their options
|
93
|
-
def
|
97
|
+
def pg_extensions
|
94
98
|
# Check postgresql version to not break on Postgresql < 9.1 during schema dump
|
95
99
|
pg_version_str = select_value('SELECT version()')
|
96
100
|
return {} unless pg_version_str =~ /^PostgreSQL (\d+\.\d+.\d+)/ && ($1 >= '9.1')
|
@@ -103,7 +107,7 @@ module PgPower::ConnectionAdapters::PostgreSQLAdapter::ExtensionMethods
|
|
103
107
|
SQL
|
104
108
|
|
105
109
|
result = select_all(sql)
|
106
|
-
result.map
|
110
|
+
formatted_result = result.map do |row|
|
107
111
|
[
|
108
112
|
row['ext_name'],
|
109
113
|
{
|
@@ -113,6 +117,6 @@ module PgPower::ConnectionAdapters::PostgreSQLAdapter::ExtensionMethods
|
|
113
117
|
]
|
114
118
|
end
|
115
119
|
|
116
|
-
Hash[
|
120
|
+
Hash[formatted_result]
|
117
121
|
end
|
118
122
|
end
|
@@ -116,7 +116,9 @@ module PgPower::CreateIndexConcurrently
|
|
116
116
|
|
117
117
|
options[:column] ||= connection.id_column_name_from_table_name(to_table)
|
118
118
|
options = options.merge(:concurrently => options[:concurrent_index])
|
119
|
-
|
119
|
+
|
120
|
+
index_options = { :concurrently => true }
|
121
|
+
enque(from_table, options[:column], index_options)
|
120
122
|
end
|
121
123
|
|
122
124
|
# GOTCHA:
|
@@ -12,7 +12,7 @@ module PgPower::SchemaDumper::ExtensionMethods
|
|
12
12
|
#
|
13
13
|
# @param [#puts] stream Stream to write to
|
14
14
|
def dump_extensions(stream)
|
15
|
-
extensions = @connection.
|
15
|
+
extensions = @connection.pg_extensions
|
16
16
|
commands = extensions.map do |extension_name, options|
|
17
17
|
result = [%Q|create_extension "#{extension_name}"|]
|
18
18
|
result << %Q|:schema_name => "#{options[:schema_name]}"| unless options[:schema_name] == 'public'
|
data/lib/pg_power/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pg_power
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Potapov Sergey
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2014-01-
|
15
|
+
date: 2014-01-29 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: pg
|
@@ -34,14 +34,14 @@ dependencies:
|
|
34
34
|
requirements:
|
35
35
|
- - ~>
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version: '
|
37
|
+
version: '4.0'
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
41
|
requirements:
|
42
42
|
- - ~>
|
43
43
|
- !ruby/object:Gem::Version
|
44
|
-
version: '
|
44
|
+
version: '4.0'
|
45
45
|
- !ruby/object:Gem::Dependency
|
46
46
|
name: rspec-rails
|
47
47
|
requirement: !ruby/object:Gem::Requirement
|
@@ -98,6 +98,20 @@ dependencies:
|
|
98
98
|
- - '>='
|
99
99
|
- !ruby/object:Gem::Version
|
100
100
|
version: '0'
|
101
|
+
- !ruby/object:Gem::Dependency
|
102
|
+
name: pry
|
103
|
+
requirement: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - '>='
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
type: :development
|
109
|
+
prerelease: false
|
110
|
+
version_requirements: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - '>='
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
101
115
|
description: ActiveRecord extensions for PostgreSQL. Provides useful tools for schema,
|
102
116
|
foreign_key, index, comment and extensios manipulations in migrations.
|
103
117
|
email:
|