redhillonrails_core 1.0.6 → 1.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +9 -0
- data/README.rdoc +39 -14
- data/VERSION +1 -1
- data/lib/red_hill_consulting/core/active_record/base.rb +1 -0
- data/lib/red_hill_consulting/core/active_record/connection_adapters/abstract_adapter.rb +5 -0
- data/lib/red_hill_consulting/core/active_record/connection_adapters/index_definition.rb +10 -8
- data/lib/red_hill_consulting/core/active_record/connection_adapters/postgresql_adapter.rb +62 -20
- data/lib/red_hill_consulting/core/active_record/schema_dumper.rb +11 -3
- data/lib/redhillonrails_core.rb +0 -2
- data/redhillonrails_core.gemspec +5 -5
- metadata +6 -4
data/CHANGELOG
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
1.0.8
|
2
|
+
* handle expressions when creating indexes
|
3
|
+
* relay on ActiveRecord add_index method when handling legacy API
|
4
|
+
1.0.7
|
5
|
+
* support for partial indexes
|
6
|
+
1.0.6
|
7
|
+
* Fixed case-sensitive indexes
|
8
|
+
1.0.5
|
9
|
+
* added missing quoting
|
1
10
|
1.0.4
|
2
11
|
* Autoloading
|
3
12
|
1.0.3
|
data/README.rdoc
CHANGED
@@ -1,14 +1,28 @@
|
|
1
|
-
|
1
|
+
= Credits
|
2
|
+
|
3
|
+
This plugin was created by harukizaemon(http://github.com/harukizaemon) but is not supported currently by him.
|
4
|
+
I've forked it to make it edge-rails compatible and to introduce new features.
|
2
5
|
|
3
6
|
= RedHill on Rails Core
|
4
7
|
|
5
|
-
RedHill on Rails Core
|
8
|
+
RedHill on Rails Core provides bunch of useful database features:
|
6
9
|
|
7
10
|
* Creating and dropping views;
|
8
11
|
* Creating and removing foreign-keys;
|
12
|
+
* Creating partial indexes (postgresql only)
|
9
13
|
* Obtaining indexes directly from a model class; and
|
10
14
|
* Determining when <code>Schema.define()</code> is running.
|
11
15
|
|
16
|
+
=== Installation
|
17
|
+
|
18
|
+
As a gem
|
19
|
+
|
20
|
+
gem install redhillonrails_core
|
21
|
+
|
22
|
+
...or as a plugin
|
23
|
+
|
24
|
+
script/plugin install http://github.com/mlomnicki/redhillonrails_core.git
|
25
|
+
|
12
26
|
=== View Support
|
13
27
|
|
14
28
|
The plugin provides a mechanism for creating and dropping views as well as
|
@@ -118,11 +132,22 @@ indexes for a given model--<code>ActiveRecord::Base</code>--class. For example:
|
|
118
132
|
|
119
133
|
Would return all the indexes for the +invoices+ table.
|
120
134
|
|
121
|
-
===
|
135
|
+
=== Partial Indexes (indexes with conditions)
|
122
136
|
|
123
|
-
|
124
|
-
|
125
|
-
|
137
|
+
Partial indexes index only a portion of the database. Only PostgreSQL supports this feature.
|
138
|
+
|
139
|
+
add_index :users, :username, :unique => true, :conditions => {:state => "active"}
|
140
|
+
|
141
|
+
=== Indexing using an arbitrary expression (PostgreSQL only)
|
142
|
+
|
143
|
+
Create expression-based indexes:
|
144
|
+
|
145
|
+
add_index :users, [:first_name, :last_name], :expression => 'LOWER(first_name || last_name)'
|
146
|
+
add_index :places, :expression => 'sin(lat) * cos(lng)', :name => 'index_places_on_something'
|
147
|
+
add_index :documents, :body, :expression => "USING gin (to_tsvector('english', body))"
|
148
|
+
|
149
|
+
Expression is a pass-through: no quoting, escaping is done on it. Presumably, this expression is
|
150
|
+
part of migrations, or at least, code under your control.
|
126
151
|
|
127
152
|
=== Case-insensitive Indexes
|
128
153
|
|
@@ -141,14 +166,14 @@ Note also that this ties in well with Rails built-in support for case-insensitiv
|
|
141
166
|
|
142
167
|
validates_uniqueness_of :name, :case_sensitive => false
|
143
168
|
|
144
|
-
===
|
169
|
+
=== Schema Defining
|
170
|
+
|
171
|
+
The plugin also adds a method--<code>defining?()</code>--to
|
172
|
+
<code>ActiveRecord::Schema</code> to indicate when <code>define()</code> is running. This is necessary
|
173
|
+
as some migration plugins must change their behaviour accordingly.
|
145
174
|
|
146
|
-
|
147
|
-
* Foreign Key Migrations (foreign_key_migrations)
|
148
|
-
* Row Version Migrations (row_version_migrations)
|
149
|
-
* Schema Validations (schema_validations)
|
175
|
+
=== Contributors
|
150
176
|
|
151
|
-
|
177
|
+
* François Beausoleil - http://github.com/francois
|
178
|
+
* Greg Barnett
|
152
179
|
|
153
|
-
This plugin is copyright 2006 by RedHill Consulting, Pty. Ltd. and is released
|
154
|
-
under the MIT license.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.8
|
@@ -26,6 +26,7 @@ module RedHillConsulting::Core::ActiveRecord
|
|
26
26
|
columns_without_redhillonrails_core
|
27
27
|
cols = columns_hash
|
28
28
|
indexes.each do |index|
|
29
|
+
next if index.columns.empty?
|
29
30
|
column_name = index.columns.reverse.detect { |name| name !~ /_id$/ } || index.columns.last
|
30
31
|
column = cols[column_name]
|
31
32
|
column.case_sensitive = index.case_sensitive?
|
@@ -58,5 +58,10 @@ module RedHillConsulting::Core::ActiveRecord::ConnectionAdapters
|
|
58
58
|
reverse_foreign_keys(name).each { |foreign_key| remove_foreign_key(foreign_key.table_name, foreign_key.name, options) }
|
59
59
|
drop_table_without_redhillonrails_core(name, options)
|
60
60
|
end
|
61
|
+
|
62
|
+
def supports_partial_indexes?
|
63
|
+
false
|
64
|
+
end
|
65
|
+
|
61
66
|
end
|
62
67
|
end
|
@@ -1,11 +1,13 @@
|
|
1
1
|
module RedHillConsulting::Core::ActiveRecord::ConnectionAdapters
|
2
|
-
|
3
|
-
|
4
|
-
@case_sensitive.nil? ? true : @case_sensitive
|
5
|
-
end
|
2
|
+
module IndexDefinition
|
3
|
+
attr_accessor :conditions, :expression
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
def case_sensitive?
|
6
|
+
@case_sensitive.nil? ? true : @case_sensitive
|
7
|
+
end
|
8
|
+
|
9
|
+
def case_sensitive=(case_sensitive)
|
10
|
+
@case_sensitive = case_sensitive
|
11
|
+
end
|
12
|
+
end
|
11
13
|
end
|
@@ -15,43 +15,74 @@ module RedHillConsulting::Core::ActiveRecord::ConnectionAdapters
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def add_index(table_name, column_name, options = {})
|
18
|
+
column_name, options = [], column_name if column_name.is_a?(Hash)
|
18
19
|
column_names = Array(column_name)
|
19
|
-
|
20
|
+
if column_names.empty?
|
21
|
+
raise ArgumentError, "No columns and :expression missing from options - cannot create index" if options[:expression].blank?
|
22
|
+
raise ArgumentError, "Index name not given. Pass :name option" if options[:name].blank?
|
23
|
+
end
|
24
|
+
|
25
|
+
index_type = options[:unique] ? "UNIQUE" : ""
|
26
|
+
index_name = options[:name] || index_name(table_name, column_names)
|
27
|
+
conditions = options[:conditions]
|
20
28
|
|
21
|
-
if
|
22
|
-
|
23
|
-
index_name = options[:name] || index_name
|
29
|
+
if column_names.empty? then
|
30
|
+
sql = "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} #{options[:expression]}"
|
24
31
|
else
|
25
|
-
|
26
|
-
end
|
32
|
+
quoted_column_names = column_names.map { |e| options[:case_sensitive] == false && e.to_s !~ /_id$/ ? "LOWER(#{quote_column_name(e)})" : quote_column_name(e) }
|
27
33
|
|
28
|
-
|
34
|
+
sql = "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names.join(", ")})"
|
35
|
+
sql += " WHERE (#{ ActiveRecord::Base.send(:sanitize_sql, conditions, quote_table_name(table_name)) })" if conditions
|
36
|
+
end
|
37
|
+
execute sql
|
38
|
+
end
|
29
39
|
|
30
|
-
|
40
|
+
def supports_partial_indexes?
|
41
|
+
true
|
31
42
|
end
|
43
|
+
|
44
|
+
INDEX_CASE_INSENSITIVE_REGEX = /\((.*LOWER\([^:]+(::text)?\).*)\)/i
|
45
|
+
INDEX_PARTIAL_REGEX = /\((.*)\)\s+WHERE (.*)$/i
|
46
|
+
INDEX_NON_BTREE_REGEX = /((?:gin|gist|hash).*)$/i
|
32
47
|
|
33
48
|
def indexes_with_redhillonrails_core(table_name, name = nil)
|
34
49
|
indexes = indexes_without_redhillonrails_core(table_name, name)
|
50
|
+
# Process indexes containg expressions and partial indexes
|
51
|
+
# Ie. consider
|
35
52
|
result = query(<<-SQL, name)
|
36
53
|
SELECT c2.relname, i.indisunique, pg_catalog.pg_get_indexdef(i.indexrelid, 0, true)
|
37
54
|
FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i
|
38
55
|
WHERE c.relname = '#{table_name}'
|
39
56
|
AND c.oid = i.indrelid AND i.indexrelid = c2.oid
|
40
|
-
AND i.indisprimary = 'f'
|
41
|
-
AND i.indexprs IS NOT NULL
|
57
|
+
AND i.indisprimary = 'f'
|
58
|
+
AND (i.indexprs IS NOT NULL OR i.indpred IS NOT NULL)
|
42
59
|
ORDER BY 1
|
43
60
|
SQL
|
44
61
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
62
|
+
|
63
|
+
# Correctly process complex indexes, ie:
|
64
|
+
# CREATE INDEX test_index ON custom_pages USING btree (lower(title::text), created_at) WHERE kind = 1 AND author_id = 3
|
65
|
+
result.each do |(index_name, unique, index_def)|
|
66
|
+
case_sensitive_match = INDEX_CASE_INSENSITIVE_REGEX.match(index_def)
|
67
|
+
partial_index_match = INDEX_PARTIAL_REGEX.match(index_def)
|
68
|
+
if case_sensitive_match || partial_index_match
|
69
|
+
# column_definitions may be ie. 'LOWER(lower)' or 'login, deleted_at' or LOWER(login), deleted_at
|
70
|
+
column_definitions = case_sensitive_match ? case_sensitive_match[1] : partial_index_match[1]
|
71
|
+
|
72
|
+
indexes.delete_if { |index| index.name == index_name } # prevent duplicated indexes
|
73
|
+
column_names = determine_index_column_names(column_definitions)
|
74
|
+
|
75
|
+
index = ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, index_name, unique == "t", column_names)
|
76
|
+
index.case_sensitive = !!case_sensitive_match
|
77
|
+
# conditions may be ie. active = true AND deleted_at IS NULL.
|
78
|
+
index.conditions = partial_index_match[2] if partial_index_match
|
79
|
+
indexes << index
|
80
|
+
|
81
|
+
elsif non_btree_match = INDEX_NON_BTREE_REGEX.match(index_def) then
|
82
|
+
indexes.delete_if { |index| index.name == index_name } # prevent duplicated indexes
|
83
|
+
|
84
|
+
index = ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, index_name, false, [])
|
85
|
+
index.expression = non_btree_match[1]
|
55
86
|
indexes << index
|
56
87
|
end
|
57
88
|
end
|
@@ -127,5 +158,16 @@ module RedHillConsulting::Core::ActiveRecord::ConnectionAdapters
|
|
127
158
|
|
128
159
|
foreign_keys
|
129
160
|
end
|
161
|
+
|
162
|
+
# Converts form like: column1, LOWER(column2)
|
163
|
+
# to: column1, column2
|
164
|
+
def determine_index_column_names(column_definitions)
|
165
|
+
column_definitions.split(", ").map do |name|
|
166
|
+
name = $1 if name =~ /^LOWER\(([^:]+)(::text)?\)$/i
|
167
|
+
name = $1 if name =~ /^"(.*)"$/
|
168
|
+
name
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
130
172
|
end
|
131
173
|
end
|
@@ -25,9 +25,17 @@ module RedHillConsulting::Core::ActiveRecord
|
|
25
25
|
def indexes_with_redhillonrails_core(table, stream)
|
26
26
|
indexes = @connection.indexes(table)
|
27
27
|
indexes.each do |index|
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
if index.expression.blank? then
|
29
|
+
stream.print " add_index #{index.table.inspect}, #{index.columns.inspect}, :name => #{index.name.inspect}"
|
30
|
+
stream.print ", :unique => true" if index.unique
|
31
|
+
stream.print ", :case_sensitive => false" unless index.case_sensitive?
|
32
|
+
stream.print ", :conditions => #{index.conditions.inspect}" unless index.conditions.blank?
|
33
|
+
else
|
34
|
+
stream.print " add_index #{index.table.inspect}"
|
35
|
+
stream.print ", :expression => #{index.expression.inspect}"
|
36
|
+
stream.print ", :name => #{index.name.inspect}"
|
37
|
+
end
|
38
|
+
|
31
39
|
stream.puts
|
32
40
|
end
|
33
41
|
stream.puts unless indexes.empty?
|
data/lib/redhillonrails_core.rb
CHANGED
@@ -35,5 +35,3 @@ ActiveRecord::ConnectionAdapters::TableDefinition.send(:include, RedHillConsulti
|
|
35
35
|
ActiveRecord::ConnectionAdapters::Column.send(:include, RedHillConsulting::Core::ActiveRecord::ConnectionAdapters::Column)
|
36
36
|
ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:include, RedHillConsulting::Core::ActiveRecord::ConnectionAdapters::AbstractAdapter)
|
37
37
|
ActiveRecord::ConnectionAdapters::SchemaStatements.send(:include, RedHillConsulting::Core::ActiveRecord::ConnectionAdapters::SchemaStatements)
|
38
|
-
|
39
|
-
|
data/redhillonrails_core.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{redhillonrails_core}
|
8
|
-
s.version = "1.0.
|
8
|
+
s.version = "1.0.8"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
-
s.authors = ["
|
12
|
-
s.date = %q{2010-
|
11
|
+
s.authors = ["Michał Łomnicki"]
|
12
|
+
s.date = %q{2010-10-19}
|
13
13
|
s.description = %q{RedHill on Rails Core is a plugin that features to support other RedHill on Rails plugins. It creates and drops views and foreign-keys or obtains indexes directly from a model class.}
|
14
14
|
s.email = %q{michal.lomnicki@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -48,14 +48,14 @@ Gem::Specification.new do |s|
|
|
48
48
|
s.homepage = %q{http://github.com/mlomnicki/redhillonrails_core}
|
49
49
|
s.rdoc_options = ["--charset=UTF-8"]
|
50
50
|
s.require_paths = ["lib"]
|
51
|
-
s.rubygems_version = %q{1.3.
|
51
|
+
s.rubygems_version = %q{1.3.7}
|
52
52
|
s.summary = %q{RedHill on Rails Core is a plugin that features to support other RedHill on Rails plugins}
|
53
53
|
|
54
54
|
if s.respond_to? :specification_version then
|
55
55
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
56
56
|
s.specification_version = 3
|
57
57
|
|
58
|
-
if Gem::Version.new(Gem::
|
58
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
59
59
|
else
|
60
60
|
end
|
61
61
|
else
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 1
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 1.0.
|
8
|
+
- 8
|
9
|
+
version: 1.0.8
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- "Micha\xC5\x82 \xC5\x81omnicki"
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-10-19 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|
@@ -65,6 +65,7 @@ rdoc_options:
|
|
65
65
|
require_paths:
|
66
66
|
- lib
|
67
67
|
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
68
69
|
requirements:
|
69
70
|
- - ">="
|
70
71
|
- !ruby/object:Gem::Version
|
@@ -72,6 +73,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
72
73
|
- 0
|
73
74
|
version: "0"
|
74
75
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
75
77
|
requirements:
|
76
78
|
- - ">="
|
77
79
|
- !ruby/object:Gem::Version
|
@@ -81,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
81
83
|
requirements: []
|
82
84
|
|
83
85
|
rubyforge_project:
|
84
|
-
rubygems_version: 1.3.
|
86
|
+
rubygems_version: 1.3.7
|
85
87
|
signing_key:
|
86
88
|
specification_version: 3
|
87
89
|
summary: RedHill on Rails Core is a plugin that features to support other RedHill on Rails plugins
|