pg_power 1.6.4 → 2.0.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 +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:
|