pg_power 1.0.1 → 1.1.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.
- data/README.markdown +27 -5
- data/lib/core_ext/active_record/connection_adapters/abstract/schema_statements.rb +37 -11
- data/lib/pg_power.rb +2 -0
- data/lib/pg_power/connection_adapters/postgresql_adapter/foreigner_methods.rb +39 -23
- data/lib/pg_power/create_index_concurrently.rb +221 -0
- data/lib/pg_power/engine.rb +17 -7
- data/lib/pg_power/errors.rb +6 -0
- data/lib/pg_power/tools.rb +1 -1
- data/lib/pg_power/version.rb +1 -1
- metadata +5 -3
data/README.markdown
CHANGED
@@ -10,6 +10,7 @@ ActiveRecord extension to get more from PostgreSQL:
|
|
10
10
|
* Set/remove comments on columns and tables.
|
11
11
|
* Use foreign keys.
|
12
12
|
* Use partial indexes.
|
13
|
+
* Run index creation concurrently.
|
13
14
|
|
14
15
|
## Environment notes
|
15
16
|
|
@@ -166,9 +167,30 @@ expressions are supported.
|
|
166
167
|
### Examples
|
167
168
|
|
168
169
|
Add an index to a column with a function
|
170
|
+
|
171
|
+
```ruby
|
172
|
+
add_index(:comments, "lower(text)")
|
173
|
+
```
|
174
|
+
|
175
|
+
## Concurrent index creation
|
176
|
+
|
177
|
+
PostgreSQL supports concurent index creation. We added that feature to migration
|
178
|
+
DSL on index and foreign keys creation.
|
179
|
+
|
180
|
+
### Examples
|
181
|
+
|
182
|
+
Add an index concurrently to a table
|
183
|
+
|
169
184
|
```ruby
|
170
|
-
add_index
|
185
|
+
add_index :table, :column_id, :concurrently => true
|
171
186
|
```
|
187
|
+
|
188
|
+
Add an index concurrently along with foreign key
|
189
|
+
|
190
|
+
```ruby
|
191
|
+
add_foreign_key :table1, :table2, :column => :column_id, :concurrent_index => true
|
192
|
+
```
|
193
|
+
|
172
194
|
## Tools
|
173
195
|
|
174
196
|
PgPower::Tools provides number of useful methods:
|
@@ -206,10 +228,10 @@ Support for JRuby:
|
|
206
228
|
|
207
229
|
## Copyright and License
|
208
230
|
|
209
|
-
Copyright (c) 2012 TMX Credit.
|
210
|
-
Initial foreign key code taken from foreigner, Copyright (c) 2009 Matthew Higgins
|
211
|
-
pg_comment Copyright (c) 2011 Arthur Shagall
|
212
|
-
Partial index Copyright (c) 2012 Marcelo Silveira
|
231
|
+
* Copyright (c) 2012 TMX Credit.
|
232
|
+
* Initial foreign key code taken from foreigner, Copyright (c) 2009 Matthew Higgins
|
233
|
+
* pg_comment Copyright (c) 2011 Arthur Shagall
|
234
|
+
* Partial index Copyright (c) 2012 Marcelo Silveira
|
213
235
|
|
214
236
|
Released under the MIT License. See the MIT-LICENSE file for more details.
|
215
237
|
|
@@ -9,13 +9,37 @@ module ActiveRecord
|
|
9
9
|
# an Array of Symbols.
|
10
10
|
#
|
11
11
|
# ====== Creating a partial index
|
12
|
-
# add_index(:accounts, [:branch_id, :party_id],
|
12
|
+
# add_index(:accounts, [:branch_id, :party_id],
|
13
|
+
# :unique => true, :concurrently => true, :where => 'active')
|
13
14
|
# generates
|
14
|
-
# CREATE UNIQUE INDEX
|
15
|
+
# CREATE UNIQUE INDEX CONCURRENTLY
|
16
|
+
# index_accounts_on_branch_id_and_party_id
|
17
|
+
# ON
|
18
|
+
# accounts(branch_id, party_id)
|
19
|
+
# WHERE
|
20
|
+
# active
|
15
21
|
#
|
16
22
|
def add_index(table_name, column_name, options = {})
|
17
|
-
|
18
|
-
|
23
|
+
name, type, creation_method, columns, opts = add_index_options(table_name, column_name, options)
|
24
|
+
|
25
|
+
# GOTCHA:
|
26
|
+
# It ensures that there is no existing index only for the case when the index
|
27
|
+
# is created concurrently to avoid changing the error behavior for default
|
28
|
+
# index creation.
|
29
|
+
# -- zekefast 2012-09-25
|
30
|
+
# GOTCHA:
|
31
|
+
# This check prevents invalid index creation, so after migration failed
|
32
|
+
# here there is no need to go to database and clean it from invalid
|
33
|
+
# indexes. But note that this handles only one of the cases when index
|
34
|
+
# creation can fail!!! All other case should be procesed manually.
|
35
|
+
# -- zekefast 2012-09-25
|
36
|
+
if options.has_key?(:concurrently) && index_exists?(table_name, column_name, options)
|
37
|
+
raise ::PgPower::IndexExistsError, "Index #{name} for `#{table_name}.#{column_name}` " \
|
38
|
+
"column can not be created concurrently, because such index already exists."
|
39
|
+
end
|
40
|
+
|
41
|
+
execute "CREATE #{type} INDEX #{creation_method} #{quote_column_name(name)} " \
|
42
|
+
"ON #{quote_table_name(table_name)} (#{columns})#{opts}"
|
19
43
|
end
|
20
44
|
|
21
45
|
# Checks to see if an index exists on a table for a given index definition.
|
@@ -24,7 +48,7 @@ module ActiveRecord
|
|
24
48
|
# # Check that a partial index exists
|
25
49
|
# index_exists?(:suppliers, :company_id, :where => 'active')
|
26
50
|
#
|
27
|
-
# # GIVEN:
|
51
|
+
# # GIVEN: 'index_suppliers_on_company_id' UNIQUE, btree (company_id) WHERE active
|
28
52
|
# index_exists?(:suppliers, :company_id, :unique => true, :where => 'active') => true
|
29
53
|
# index_exists?(:suppliers, :company_id, :unique => true) => false
|
30
54
|
#
|
@@ -88,14 +112,16 @@ module ActiveRecord
|
|
88
112
|
# Added support for partial indexes implemented using the :where option
|
89
113
|
#
|
90
114
|
def add_index_options(table_name, column_name, options = {})
|
91
|
-
column_names
|
92
|
-
index_name
|
115
|
+
column_names = Array(column_name)
|
116
|
+
index_name = index_name(table_name, :column => column_names)
|
117
|
+
index_creation_method = nil
|
93
118
|
|
94
119
|
if Hash === options # legacy support, since this param was a string
|
95
|
-
index_type = options[:unique] ?
|
120
|
+
index_type = options[:unique] ? 'UNIQUE' : ''
|
121
|
+
index_creation_method = options[:concurrently] ? 'CONCURRENTLY' : ''
|
96
122
|
index_name = options[:name].to_s if options.key?(:name)
|
97
123
|
if supports_partial_index?
|
98
|
-
index_options = options[:where] ? " WHERE #{options[:where]}" :
|
124
|
+
index_options = options[:where] ? " WHERE #{options[:where]}" : ''
|
99
125
|
end
|
100
126
|
else
|
101
127
|
index_type = options
|
@@ -107,9 +133,9 @@ module ActiveRecord
|
|
107
133
|
if index_name_exists?(table_name, index_name, false)
|
108
134
|
raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists"
|
109
135
|
end
|
110
|
-
index_columns = quoted_columns_for_index(column_names, options).join(
|
136
|
+
index_columns = quoted_columns_for_index(column_names, options).join(', ')
|
111
137
|
|
112
|
-
[index_name, index_type, index_columns, index_options]
|
138
|
+
[index_name, index_type, index_creation_method, index_columns, index_options]
|
113
139
|
end
|
114
140
|
protected :add_index_options
|
115
141
|
|
data/lib/pg_power.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "pg_power/engine"
|
2
|
+
require "pg_power/errors"
|
2
3
|
|
3
4
|
# Rails engine which allows to use some PostgreSQL features:
|
4
5
|
# * Schemas.
|
@@ -13,4 +14,5 @@ module PgPower
|
|
13
14
|
autoload :Tools
|
14
15
|
autoload :Migration
|
15
16
|
autoload :ConnectionAdapters
|
17
|
+
autoload :CreateIndexConcurrently
|
16
18
|
end
|
@@ -1,8 +1,4 @@
|
|
1
1
|
module PgPower # :nodoc:
|
2
|
-
# Raised when an unexpected index exists
|
3
|
-
class IndexExistsError < StandardError
|
4
|
-
end
|
5
|
-
|
6
2
|
# Provides methods to extend {ActiveRecord::ConnectionAdapters::PostgreSQLAdapter}
|
7
3
|
# to support foreign keys feature.
|
8
4
|
module ConnectionAdapters::PostgreSQLAdapter::ForeignerMethods
|
@@ -70,30 +66,51 @@ module PgPower # :nodoc:
|
|
70
66
|
#
|
71
67
|
# Ensures that an index is created for the foreign key, unless :exclude_index is true.
|
72
68
|
#
|
73
|
-
# Raises a [PgPower::IndexExistsError] when :exclude_index is true, but the index already exists.
|
74
|
-
#
|
75
69
|
# == Options:
|
76
70
|
# * :column
|
77
71
|
# * :primary_key
|
78
72
|
# * :dependent
|
79
|
-
# * :exclude_index
|
73
|
+
# * :exclude_index [Boolean]
|
74
|
+
# * :concurrent_index [Boolean]
|
80
75
|
#
|
81
|
-
# @param [String, Symbol]
|
82
|
-
# @param [String, Symbol]
|
83
|
-
# @param [Hash]
|
76
|
+
# @param [String, Symbol] from_table
|
77
|
+
# @param [String, Symbol] to_table
|
78
|
+
# @param [Hash] options
|
79
|
+
# @option options [String, Symbol] :column
|
80
|
+
# @option options [String, Symbol] :primary_key
|
81
|
+
# @option options [Hash] :dependent
|
82
|
+
# @option options [Boolean] :exclude_index
|
83
|
+
# @option options [Boolean] :concurrent_index
|
84
84
|
#
|
85
|
+
# @raise [PgPower::IndexExistsError] when :exclude_index is true, but the index already exists
|
85
86
|
def add_foreign_key(from_table, to_table, options = {})
|
86
|
-
options[:column]
|
87
|
-
options[:exclude_index]
|
87
|
+
options[:column] ||= id_column_name_from_table_name(to_table)
|
88
|
+
options[:exclude_index] ||= false
|
88
89
|
|
89
|
-
if index_exists?(from_table, options[:column])
|
90
|
-
raise PgPower::IndexExistsError,
|
90
|
+
if index_exists?(from_table, options[:column]) && !options[:exclude_index]
|
91
|
+
raise PgPower::IndexExistsError,
|
92
|
+
"The index, #{index_name(from_table, options[:column])}, already exists." \
|
93
|
+
" Use :exclude_index => true when adding the foreign key."
|
91
94
|
end
|
92
95
|
|
93
96
|
sql = "ALTER TABLE #{quote_table_name(from_table)} #{add_foreign_key_sql(from_table, to_table, options)}"
|
94
97
|
execute(sql)
|
95
98
|
|
96
|
-
|
99
|
+
# GOTCHA:
|
100
|
+
# Index can not be created concurrently inside transaction in PostgreSQL.
|
101
|
+
# So, in case of concurrently created index with foreign key only
|
102
|
+
# foreign key will be created inside migration transaction and after
|
103
|
+
# closing transaction queries for index creation will be send to database.
|
104
|
+
# That's why I prevent here normal index creation in case of
|
105
|
+
# `concurrent_index` option is given.
|
106
|
+
# NOTE: Index creation after closing migration transaction could lead
|
107
|
+
# to weird effects when transaction moves smoothly, but index
|
108
|
+
# creation with error. In that case transaction will not be rolled back.
|
109
|
+
# As it was closed before even index was attempted to create.
|
110
|
+
# -- zekefast 2012-09-12
|
111
|
+
unless options[:exclude_index] || options[:concurrent_index]
|
112
|
+
add_index(from_table, options[:column])
|
113
|
+
end
|
97
114
|
end
|
98
115
|
|
99
116
|
# Returns chunk of SQL to add foreign key based on table names and options.
|
@@ -130,13 +147,13 @@ module PgPower # :nodoc:
|
|
130
147
|
#
|
131
148
|
def remove_foreign_key(from_table, to_table_or_options_hash, options={})
|
132
149
|
if Hash === to_table_or_options_hash
|
133
|
-
options
|
134
|
-
column
|
135
|
-
foreign_key_name =
|
136
|
-
column
|
150
|
+
options = to_table_or_options_hash
|
151
|
+
column = options[:column]
|
152
|
+
foreign_key_name = foreign_key_name(from_table, column, options)
|
153
|
+
column ||= id_column_name_from_foreign_key_metadata(from_table, foreign_key_name)
|
137
154
|
else
|
138
|
-
column
|
139
|
-
foreign_key_name =
|
155
|
+
column = id_column_name_from_table_name(to_table_or_options_hash)
|
156
|
+
foreign_key_name = foreign_key_name(from_table, column)
|
140
157
|
end
|
141
158
|
|
142
159
|
execute "ALTER TABLE #{quote_table_name(from_table)} #{remove_foreign_key_sql(foreign_key_name)}"
|
@@ -154,7 +171,6 @@ module PgPower # :nodoc:
|
|
154
171
|
def id_column_name_from_table_name(table)
|
155
172
|
"#{table.to_s.split('.').last.singularize}_id"
|
156
173
|
end
|
157
|
-
private :id_column_name_from_table_name
|
158
174
|
|
159
175
|
# Extracts the foreign key column id from the foreign key metadata
|
160
176
|
# @param [String, Symbol] from_table
|
@@ -165,7 +181,7 @@ module PgPower # :nodoc:
|
|
165
181
|
this_key.options[:column]
|
166
182
|
end
|
167
183
|
private :id_column_name_from_foreign_key_metadata
|
168
|
-
|
184
|
+
|
169
185
|
# Builds default name for constraint
|
170
186
|
def foreign_key_name(table, column, options = {})
|
171
187
|
if options[:name]
|
@@ -0,0 +1,221 @@
|
|
1
|
+
# Adds ability to configure in migration how index will be created.
|
2
|
+
# See more details how to create index concurrently in PostgreSQL at
|
3
|
+
# (see http://www.postgresql.org/docs/9.2/static/sql-createindex.html#SQL-CREATEINDEX-CONCURRENTLY).
|
4
|
+
#
|
5
|
+
# There are several things you should be aware when use option to create index
|
6
|
+
# concurrently.
|
7
|
+
# Index can not be created concurrently inside transaction and such indexes
|
8
|
+
# creation will be postponed till migration transaction will be closed.
|
9
|
+
# In case of migration failure and transaction was rolled back indexes will not
|
10
|
+
# be created concurrently. But if indexes which should be created concurrently
|
11
|
+
# run with errors migration's transaction won't be rolled back. Error in that
|
12
|
+
# case will be raised and migration process will be stoped.
|
13
|
+
#
|
14
|
+
# Migrations can not ensure that all indexes that tend to be created
|
15
|
+
# concurrently were created even if the query for such index creation run
|
16
|
+
# without errors. Such indexes creation are deferred because of its nature.
|
17
|
+
# So, it's up to you to ensure that indexes was really created or remove
|
18
|
+
# partially created invalid indexes.
|
19
|
+
#
|
20
|
+
# :concurrent_index option conflicts with :exclude_index option in method
|
21
|
+
# `add_foreign_key`. So, if you put them together exception will be raised.
|
22
|
+
#
|
23
|
+
# @example
|
24
|
+
#
|
25
|
+
# class AddIndexToNameForUsers < ActiveRecord::Migration
|
26
|
+
# def change
|
27
|
+
# add_index :users, :name, :concurrently => true
|
28
|
+
# end
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# # or with foreign key
|
32
|
+
#
|
33
|
+
# class AddForeignKeyToRoleIdForUsers < ActiveRecord::Migration
|
34
|
+
# def change
|
35
|
+
# add_foreign_key :users, :roles, :concurrent_index => true
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
module PgPower::CreateIndexConcurrently
|
40
|
+
# Provides ability to postpone index creation queries in migrations.
|
41
|
+
#
|
42
|
+
# Overrides `add_index` and `add_foreign_key` methods for migration to be
|
43
|
+
# able to prevent indexes creation inside scope of transaction if they have to
|
44
|
+
# be created concurrently.
|
45
|
+
# Allows to run creation of postponed indexes.
|
46
|
+
#
|
47
|
+
# This module included into ActiveRecord::Migration class to extend it with
|
48
|
+
# new features.
|
49
|
+
#
|
50
|
+
# All postponed index creation queries are stored inside migration instance.
|
51
|
+
module Migration
|
52
|
+
# @attribute postponed_queries
|
53
|
+
# @return [Array] list of arguments to call `add_index` method.
|
54
|
+
# @private
|
55
|
+
attr_accessor :postponed_queries
|
56
|
+
private :postponed_queries, :postponed_queries=
|
57
|
+
|
58
|
+
|
59
|
+
# Adds a new index to the table. +column_name+ can be a single Symbol, or
|
60
|
+
# an Array of Symbols.
|
61
|
+
#
|
62
|
+
# @param [Symbol, String] table_name
|
63
|
+
# @param [Symbol, String, Array<Symbol, String>] column_name
|
64
|
+
# @param [optional, Hash] options
|
65
|
+
# @option options [Boolean] :unique
|
66
|
+
# @option options [Boolean] :concurrently
|
67
|
+
# @option options [String] :where
|
68
|
+
#
|
69
|
+
# @return [nil]
|
70
|
+
#
|
71
|
+
# @see ActiveRecord::ConnectionAdapters::SchemaStatements.add_index in pg_power gem
|
72
|
+
def add_index(table_name, column_name, options = {}, &block)
|
73
|
+
table_name = ::ActiveRecord::Migrator.proper_table_name(table_name)
|
74
|
+
# GOTCHA:
|
75
|
+
# checks if index should be created concurretnly then put it into
|
76
|
+
# the queue to wait till queue processing will be called (should be
|
77
|
+
# happended after closing transaction).
|
78
|
+
# Otherwise just delegate call to PgPower's `add_index`.
|
79
|
+
# Block is given for future compatibility.
|
80
|
+
# -- zekefast 2012-09-12
|
81
|
+
unless options[:concurrently]
|
82
|
+
return connection.add_index(table_name, column_name, options, &block)
|
83
|
+
end
|
84
|
+
|
85
|
+
enque(table_name, column_name, options, &block)
|
86
|
+
nil
|
87
|
+
end
|
88
|
+
|
89
|
+
# Adds foreign key.
|
90
|
+
#
|
91
|
+
# == Options:
|
92
|
+
# * :column
|
93
|
+
# * :primary_key
|
94
|
+
# * :dependent
|
95
|
+
# * :exclude_index [Boolean]
|
96
|
+
# * :concurrent_index [Boolean]
|
97
|
+
#
|
98
|
+
# @param [String, Symbol] from_table
|
99
|
+
# @param [String, Symbol] to_table
|
100
|
+
# @param [Hash] options
|
101
|
+
# @option options [String, Symbol] :column
|
102
|
+
# @option options [String, Symbol] :primary_key
|
103
|
+
# @option options [Hash] :dependent
|
104
|
+
# @option options [Boolean] :exclude_index
|
105
|
+
# @option options [Boolean] :concurrent_index
|
106
|
+
#
|
107
|
+
# @raise [ArgumentError] in case of conflicted option were set
|
108
|
+
#
|
109
|
+
# @see ::PgPower::ConnectionAdapters::PostgreSQLAdapter::ForeignerMethods.add_foreign_key
|
110
|
+
def add_foreign_key(from_table, to_table, options = {}, &block)
|
111
|
+
from_table = ::ActiveRecord::Migrator.proper_table_name(from_table)
|
112
|
+
if options[:concurrent_index]
|
113
|
+
if options[:exclude_index]
|
114
|
+
raise ArgumentError, 'Conflicted options(exclude_index, concurrent_index) was found, both are set to true.'
|
115
|
+
end
|
116
|
+
|
117
|
+
options[:column] ||= connection.id_column_name_from_table_name(to_table)
|
118
|
+
options = options.merge(:concurrently => options[:concurrent_index])
|
119
|
+
enque(from_table, options[:column], options)
|
120
|
+
end
|
121
|
+
|
122
|
+
# GOTCHA:
|
123
|
+
# proceed foreign key creation, but giving :concurrent_index => true
|
124
|
+
# prevent normal index creation in PgPower's `add_foreign_key`.
|
125
|
+
# So, postponed creation could be done after transaction.
|
126
|
+
# -- zekefast 2012-09-12
|
127
|
+
connection.add_foreign_key(from_table, to_table, options, &block)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Execute all postponed index creation.
|
131
|
+
#
|
132
|
+
# @return [::PgPower::CreateIndexConcurrently::Migration]
|
133
|
+
def process_postponed_queries
|
134
|
+
Array(@postponed_queries).each do |arguments, block|
|
135
|
+
connection.add_index(*arguments, &block)
|
136
|
+
end
|
137
|
+
|
138
|
+
clear_queue
|
139
|
+
|
140
|
+
self
|
141
|
+
end
|
142
|
+
|
143
|
+
# Clean postponed queries' queue.
|
144
|
+
#
|
145
|
+
# @return [::PgPower::CreateIndexConcurrently::Migration] migration
|
146
|
+
def clear_queue
|
147
|
+
@postponed_queries = []
|
148
|
+
|
149
|
+
self
|
150
|
+
end
|
151
|
+
private :clear_queue
|
152
|
+
|
153
|
+
# Add to the queue add_index call parameters to be able execute call later.
|
154
|
+
#
|
155
|
+
# @param [Array] arguments
|
156
|
+
# @param [Proc] block
|
157
|
+
#
|
158
|
+
# @return [::PgPower::CreateIndexConcurrently::Migration]
|
159
|
+
def enque(*arguments, &block)
|
160
|
+
@postponed_queries ||= []
|
161
|
+
@postponed_queries << [arguments, block]
|
162
|
+
|
163
|
+
self
|
164
|
+
end
|
165
|
+
private :enque
|
166
|
+
end
|
167
|
+
|
168
|
+
# Allows to call `process_postponed_queries` on MigrationProxy instances.
|
169
|
+
# So, (see ::PgPower::CreateIndexConcurrently::Migrator) could run index
|
170
|
+
# creation concurrently.
|
171
|
+
#
|
172
|
+
# Default delegation in (see ActiveRecord::MigrationProxy) allows to call
|
173
|
+
# only several methods.
|
174
|
+
module MigrationProxy
|
175
|
+
def self.included(klass)
|
176
|
+
klass.delegate :process_postponed_queries, :to => :migration
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# Runs posponed index creation for each migration.
|
181
|
+
#
|
182
|
+
# This module included into (see ::ActiveRecord::Migrator) class to make possible
|
183
|
+
# to execute queries for postponed index creation after closing migration's
|
184
|
+
# transaction.
|
185
|
+
#
|
186
|
+
# @see ::ActiveRecord::Migrator.migrate
|
187
|
+
# @see ::ActiveRecord::Migrator.ddl_transaction
|
188
|
+
module Migrator
|
189
|
+
extend ActiveSupport::Concern
|
190
|
+
|
191
|
+
def self.included(klass)
|
192
|
+
klass.alias_method_chain :ddl_transaction, :postponed_queries
|
193
|
+
end
|
194
|
+
|
195
|
+
# Override (see ::ActiveRecord::Migrator.ddl_transaction) to call
|
196
|
+
# (see ::PgPower::CreateIndexConcurrently::Migration.process_postponed_queries)
|
197
|
+
# immediately after transaction.
|
198
|
+
#
|
199
|
+
# @see ::ActiveRecord::Migrator.ddl_transaction
|
200
|
+
def ddl_transaction_with_postponed_queries(*args, &block)
|
201
|
+
ddl_transaction_without_postponed_queries(*args, &block)
|
202
|
+
|
203
|
+
# GOTCHA:
|
204
|
+
# This might be a bit tricky, but I've decided that this is the best
|
205
|
+
# way to retrieve migration instance after closing transaction.
|
206
|
+
# The problem that (see ::ActiveRecord::Migrator) doesn't provide any
|
207
|
+
# access to recently launched migration. All logic to iterate through
|
208
|
+
# set of migrations incapsulated in (see ::ActiveRecord::Migrator.migrate)
|
209
|
+
# method.
|
210
|
+
# So, to get access to migration you need to override `migrate` method
|
211
|
+
# and duplicated all logic inside it, plus add call to
|
212
|
+
# `process_postponed_queries`.
|
213
|
+
# I've decided this is less forward compatible then retrieving
|
214
|
+
# value of `migration` variable in context where block
|
215
|
+
# given to `ddl_transaction` method was created.
|
216
|
+
# -- zekefast 2012-09-12
|
217
|
+
migration = block.binding.eval('migration')
|
218
|
+
migration.process_postponed_queries
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
data/lib/pg_power/engine.rb
CHANGED
@@ -9,12 +9,10 @@ module PgPower
|
|
9
9
|
'errors',
|
10
10
|
'connection_adapters/postgresql_adapter',
|
11
11
|
'connection_adapters/abstract/schema_statements'].each do |path|
|
12
|
-
require PgPower::Engine.root + 'lib/core_ext/active_record/' + path
|
12
|
+
require ::PgPower::Engine.root + 'lib/core_ext/active_record/' + path
|
13
13
|
end
|
14
14
|
|
15
|
-
ActiveRecord::SchemaDumper.class_eval
|
16
|
-
include PgPower::SchemaDumper
|
17
|
-
end
|
15
|
+
ActiveRecord::SchemaDumper.class_eval { include ::PgPower::SchemaDumper }
|
18
16
|
|
19
17
|
if defined?(ActiveRecord::Migration::CommandRecorder)
|
20
18
|
ActiveRecord::Migration::CommandRecorder.class_eval do
|
@@ -22,12 +20,24 @@ module PgPower
|
|
22
20
|
end
|
23
21
|
end
|
24
22
|
|
23
|
+
# Follow three include statements add support for concurrently
|
24
|
+
# index creation in migrations.
|
25
|
+
ActiveRecord::Migration.class_eval do
|
26
|
+
include ::PgPower::CreateIndexConcurrently::Migration
|
27
|
+
end
|
28
|
+
ActiveRecord::Migrator.class_eval do
|
29
|
+
include ::PgPower::CreateIndexConcurrently::Migrator
|
30
|
+
end
|
31
|
+
ActiveRecord::MigrationProxy.class_eval do
|
32
|
+
include ::PgPower::CreateIndexConcurrently::MigrationProxy
|
33
|
+
end
|
34
|
+
|
25
35
|
ActiveRecord::ConnectionAdapters::Table.module_eval do
|
26
|
-
include PgPower::ConnectionAdapters::Table
|
36
|
+
include ::PgPower::ConnectionAdapters::Table
|
27
37
|
end
|
28
38
|
|
29
39
|
ActiveRecord::ConnectionAdapters::AbstractAdapter.module_eval do
|
30
|
-
include PgPower::ConnectionAdapters::AbstractAdapter
|
40
|
+
include ::PgPower::ConnectionAdapters::AbstractAdapter
|
31
41
|
end
|
32
42
|
|
33
43
|
if defined?(ActiveRecord::ConnectionAdapters::JdbcAdapter)
|
@@ -37,7 +47,7 @@ module PgPower
|
|
37
47
|
end
|
38
48
|
|
39
49
|
sql_adapter_class.class_eval do
|
40
|
-
include PgPower::ConnectionAdapters::PostgreSQLAdapter
|
50
|
+
include ::PgPower::ConnectionAdapters::PostgreSQLAdapter
|
41
51
|
end
|
42
52
|
|
43
53
|
end
|
data/lib/pg_power/tools.rb
CHANGED
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: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2012-09-
|
14
|
+
date: 2012-09-26 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: pg
|
@@ -173,7 +173,9 @@ files:
|
|
173
173
|
- lib/pg_power/connection_adapters/table.rb
|
174
174
|
- lib/pg_power/connection_adapters/table/comment_methods.rb
|
175
175
|
- lib/pg_power/connection_adapters/table/foreigner_methods.rb
|
176
|
+
- lib/pg_power/create_index_concurrently.rb
|
176
177
|
- lib/pg_power/engine.rb
|
178
|
+
- lib/pg_power/errors.rb
|
177
179
|
- lib/pg_power/migration.rb
|
178
180
|
- lib/pg_power/migration/command_recorder.rb
|
179
181
|
- lib/pg_power/migration/command_recorder/comment_methods.rb
|
@@ -200,7 +202,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
200
202
|
version: '0'
|
201
203
|
segments:
|
202
204
|
- 0
|
203
|
-
hash:
|
205
|
+
hash: -621483421206137072
|
204
206
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
205
207
|
none: false
|
206
208
|
requirements:
|