schema_plus_pg_indexes 0.1.8 → 0.1.9
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.md +1 -0
- data/lib/schema_plus_pg_indexes/middleware/postgresql/migration.rb +15 -2
- data/lib/schema_plus_pg_indexes/version.rb +1 -1
- data/spec/index_spec.rb +58 -139
- data/spec/schema_spec.rb +88 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef5750ecbe4c6463189603e306f2acfd9339753f
|
4
|
+
data.tar.gz: aa49a2061f4600f9652f4cf238c605db35d6c153
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64722adf53223e3ade5a1169bf70873bccd90d1ececd0a3d705f8770aa79f6fac2b9c7171966edc56883e31c580c972a59855b3f34001219ea9f337a9376bf22
|
7
|
+
data.tar.gz: 8a59bb3f09a07c8ad2036b3fe7ac1b72cc2fb6adcb287ffb33ee5c0969351d10e3935e9c65f21580d678270168e055475307b371dd68e43b55ab8f15fb644aa6
|
data/README.md
CHANGED
@@ -61,6 +61,7 @@ schema_plus_pg_indexes is tested on
|
|
61
61
|
|
62
62
|
## History
|
63
63
|
|
64
|
+
* v0.1.9 - Bug fix: multiple expression indexes (#8)
|
64
65
|
* v0.1.8 - Bug fix: expression with operator class (#7)
|
65
66
|
* v0.1.7 - Bug fix: mix of columns & expressions (#5)
|
66
67
|
* v0.1.6 - Bug fix: operator class & multiple columns (#4). Thanks to [@nbudin](https://github.com/nbudin)
|
@@ -12,11 +12,24 @@ module SchemaPlusPgIndexes
|
|
12
12
|
env.options[proper] = env.options.delete(deprecated)
|
13
13
|
end
|
14
14
|
end
|
15
|
+
|
16
|
+
case env.caller.class.name
|
17
|
+
when /TableDefinition/
|
18
|
+
# When index creation is in table definition, create a dummy value for column_names,
|
19
|
+
# since index definitions are indexed by column names
|
20
|
+
env.column_names = dummy_column_names(env) if env.column_names.blank?
|
21
|
+
else
|
22
|
+
# For actual index creation, strip out the dummy column name
|
23
|
+
# value
|
24
|
+
env.column_names = [] if env.column_names == dummy_column_names(env)
|
25
|
+
end
|
15
26
|
end
|
16
|
-
end
|
17
27
|
|
28
|
+
def dummy_column_names(env)
|
29
|
+
["--expression--", env.options[:expression]]
|
30
|
+
end
|
31
|
+
end
|
18
32
|
end
|
19
33
|
end
|
20
34
|
end
|
21
35
|
end
|
22
|
-
|
data/spec/index_spec.rb
CHANGED
@@ -4,162 +4,81 @@ describe "index" do
|
|
4
4
|
|
5
5
|
let(:migration) { ::ActiveRecord::Migration }
|
6
6
|
|
7
|
-
|
7
|
+
class User < ::ActiveRecord::Base ; end
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
User.reset_column_information
|
13
|
-
end
|
14
|
-
|
15
|
-
context "extra features" do
|
16
|
-
|
17
|
-
before(:each) do
|
18
|
-
define_schema do
|
19
|
-
create_table :users do |t|
|
20
|
-
t.string :login
|
21
|
-
t.text :address
|
22
|
-
t.jsonb :json_col
|
23
|
-
t.datetime :deleted_at
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
it "should assign expression, where and using" do
|
29
|
-
add_index(:users, :expression => "USING hash (upper(login)) WHERE deleted_at IS NULL", :name => 'users_login_index')
|
30
|
-
index = User.indexes.detect { |i| i.expression.present? }
|
31
|
-
expect(index.expression).to eq("upper((login)::text)")
|
32
|
-
expect(index.where).to eq("(deleted_at IS NULL)")
|
33
|
-
expect(index.using).to eq(:hash)
|
34
|
-
end
|
35
|
-
|
36
|
-
it "should allow to specify expression, where and using separately" do
|
37
|
-
add_index(:users, :using => "hash", :expression => "upper(login)", :where => "deleted_at IS NULL", :name => 'users_login_index')
|
38
|
-
index = User.indexes.detect { |i| i.expression.present? }
|
39
|
-
expect(index.expression).to eq("upper((login)::text)")
|
40
|
-
expect(index.where).to eq("(deleted_at IS NULL)")
|
41
|
-
expect(index.using).to eq(:hash)
|
42
|
-
end
|
43
|
-
|
44
|
-
it "should assign operator_class" do
|
45
|
-
add_index(:users, :login, :operator_class => 'varchar_pattern_ops')
|
46
|
-
expect(index_for(:login).operator_classes).to eq({"login" => 'varchar_pattern_ops'})
|
47
|
-
end
|
48
|
-
|
49
|
-
it "should assign multiple operator_classes" do
|
50
|
-
add_index(:users, [:login, :address], :operator_class => {:login => 'varchar_pattern_ops', :address => 'text_pattern_ops'})
|
51
|
-
expect(index_for([:login, :address]).operator_classes).to eq({"login" => 'varchar_pattern_ops', "address" => 'text_pattern_ops'})
|
52
|
-
end
|
53
|
-
|
54
|
-
it "should allow to specify actual expression only" do
|
55
|
-
add_index(:users, :expression => "upper(login)", :name => 'users_login_index')
|
56
|
-
index = User.indexes.detect { |i| i.name == 'users_login_index' }
|
57
|
-
expect(index.expression).to eq("upper((login)::text)")
|
58
|
-
end
|
59
|
-
|
60
|
-
it "should create proper sql with jsonb expressions (schema_plus #212)" do
|
61
|
-
add_index :users, :name => "json_expression", :using => :gin, :expression => "(json_col -> 'field')"
|
62
|
-
index = User.indexes.detect(&its.name == "json_expression")
|
63
|
-
expect(index.expression).to eq("(json_col -> 'field'::text)")
|
64
|
-
end
|
65
|
-
|
66
|
-
it "should raise if no column given and expression is missing" do
|
67
|
-
expect { add_index(:users, :name => 'users_login_index') }.to raise_error(ArgumentError, /expression/)
|
68
|
-
end
|
69
|
-
|
70
|
-
it "should raise if expression without name is given" do
|
71
|
-
expect { add_index(:users, :expression => "upper(login)") }.to raise_error(ArgumentError, /name/)
|
72
|
-
end
|
9
|
+
after(:each) do
|
10
|
+
User.reset_column_information
|
11
|
+
end
|
73
12
|
|
74
|
-
|
75
|
-
|
13
|
+
before(:each) do
|
14
|
+
define_schema do
|
15
|
+
create_table :users do |t|
|
16
|
+
t.string :login
|
17
|
+
t.text :address
|
18
|
+
t.jsonb :json_col
|
19
|
+
t.datetime :deleted_at
|
76
20
|
end
|
77
|
-
|
78
21
|
end
|
22
|
+
end
|
79
23
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
end
|
88
|
-
expect(User.indexes.first.expression).to eq("upper((login)::text)")
|
89
|
-
expect(User.indexes.first.name).to eq("no_column")
|
90
|
-
end
|
24
|
+
it "should assign expression, where and using" do
|
25
|
+
add_index(:users, :expression => "USING hash (upper(login)) WHERE deleted_at IS NULL", :name => 'users_login_index')
|
26
|
+
index = User.indexes.detect { |i| i.expression.present? }
|
27
|
+
expect(index.expression).to eq("upper((login)::text)")
|
28
|
+
expect(index.where).to eq("(deleted_at IS NULL)")
|
29
|
+
expect(index.using).to eq(:hash)
|
30
|
+
end
|
91
31
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
expect(User.indexes.first.name).to eq("index_users_on_login")
|
100
|
-
expect(User.indexes.first.columns).to be_empty
|
101
|
-
end
|
32
|
+
it "should allow to specify expression, where and using separately" do
|
33
|
+
add_index(:users, :using => "hash", :expression => "upper(login)", :where => "deleted_at IS NULL", :name => 'users_login_index')
|
34
|
+
index = User.indexes.detect { |i| i.expression.present? }
|
35
|
+
expect(index.expression).to eq("upper((login)::text)")
|
36
|
+
expect(index.where).to eq("(deleted_at IS NULL)")
|
37
|
+
expect(index.using).to eq(:hash)
|
38
|
+
end
|
102
39
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
t.string :login, index: { with: "name", expression: "upper(login)" }
|
108
|
-
end
|
109
|
-
end
|
110
|
-
expect(User.indexes.first.expression).to eq("upper((login)::text)")
|
111
|
-
expect(User.indexes.first.name).to eq("index_users_on_login_and_name")
|
112
|
-
expect(User.indexes.first.columns).to eq(["name"])
|
113
|
-
end
|
40
|
+
it "should assign operator_class" do
|
41
|
+
add_index(:users, :login, :operator_class => 'varchar_pattern_ops')
|
42
|
+
expect(index_for(:login).operator_classes).to eq({"login" => 'varchar_pattern_ops'})
|
43
|
+
end
|
114
44
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
t.string :login, index: { expression: "upper(name)" }
|
120
|
-
end
|
121
|
-
end
|
122
|
-
expect(User.indexes.first.expression).to eq("upper((name)::text)")
|
123
|
-
expect(User.indexes.first.name).to eq("index_users_on_login")
|
124
|
-
expect(User.indexes.first.columns).to eq(["login"])
|
125
|
-
end
|
126
|
-
end
|
45
|
+
it "should assign multiple operator_classes" do
|
46
|
+
add_index(:users, [:login, :address], :operator_class => {:login => 'varchar_pattern_ops', :address => 'text_pattern_ops'})
|
47
|
+
expect(index_for([:login, :address]).operator_classes).to eq({"login" => 'varchar_pattern_ops', "address" => 'text_pattern_ops'})
|
48
|
+
end
|
127
49
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
end
|
134
|
-
change_table :users do |t|
|
135
|
-
t.index :expression => "upper(login)", name: "no_column"
|
136
|
-
end
|
137
|
-
end
|
138
|
-
expect(User.indexes.first.expression).to eq("upper((login)::text)")
|
139
|
-
expect(User.indexes.first.name).to eq("no_column")
|
140
|
-
end
|
141
|
-
end
|
50
|
+
it "should allow to specify actual expression only" do
|
51
|
+
add_index(:users, :expression => "upper(login)", :name => 'users_login_index')
|
52
|
+
index = User.indexes.detect { |i| i.name == 'users_login_index' }
|
53
|
+
expect(index.expression).to eq("upper((login)::text)")
|
54
|
+
end
|
142
55
|
|
143
|
-
|
56
|
+
it "should create proper sql with jsonb expressions (schema_plus #212)" do
|
57
|
+
add_index :users, :name => "json_expression", :using => :gin, :expression => "(json_col -> 'field')"
|
58
|
+
index = User.indexes.detect(&its.name == "json_expression")
|
59
|
+
expect(index.expression).to eq("(json_col -> 'field'::text)")
|
60
|
+
end
|
144
61
|
|
145
|
-
|
146
|
-
|
147
|
-
|
62
|
+
it "should raise if no column given and expression is missing" do
|
63
|
+
expect { add_index(:users, :name => 'users_login_index') }.to raise_error(ArgumentError, /expression/)
|
64
|
+
end
|
148
65
|
|
66
|
+
it "should raise if expression without name is given" do
|
67
|
+
expect { add_index(:users, :expression => "upper(login)") }.to raise_error(ArgumentError, /name/)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should raise if expression is given and case_sensitive is false" do
|
71
|
+
expect { add_index(:users, :name => 'users_login_index', :expression => "upper(login)", :case_sensitive => false) }.to raise_error(ArgumentError, /use LOWER/i)
|
149
72
|
end
|
150
73
|
|
151
74
|
protected
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
end
|
156
|
-
User.reset_column_information
|
75
|
+
|
76
|
+
def index_for(column_names)
|
77
|
+
User.indexes.detect { |i| i.columns == Array(column_names).collect(&:to_s) }
|
157
78
|
end
|
158
79
|
|
159
|
-
def
|
160
|
-
migration.
|
161
|
-
migration.remove_index(*args)
|
162
|
-
end
|
80
|
+
def add_index(*args)
|
81
|
+
migration.add_index(*args)
|
163
82
|
User.reset_column_information
|
164
83
|
end
|
165
84
|
|
data/spec/schema_spec.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe "schema" do
|
5
|
+
|
6
|
+
class User < ::ActiveRecord::Base ; end
|
7
|
+
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
User.reset_column_information
|
11
|
+
end
|
12
|
+
|
13
|
+
context "create table" do
|
14
|
+
it "defines index with expression only" do
|
15
|
+
define_schema do
|
16
|
+
create_table :users do |t|
|
17
|
+
t.string :login
|
18
|
+
t.index :expression => "upper(login)", name: "no_column"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
expect(User.indexes.first.expression).to eq("upper((login)::text)")
|
22
|
+
expect(User.indexes.first.name).to eq("no_column")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "defines two indexes with expression only" do
|
26
|
+
define_schema do
|
27
|
+
create_table :users do |t|
|
28
|
+
t.string :one
|
29
|
+
t.string :two
|
30
|
+
t.index :expression => "upper(one)", name: "index_one"
|
31
|
+
t.index :expression => "upper(two)", name: "index_two"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
expect(User.indexes.map(&:name)).to eq(["index_one", "index_two"])
|
35
|
+
expect(User.indexes.map(&:expression)).to eq(["upper((one)::text)", "upper((two)::text)"])
|
36
|
+
end
|
37
|
+
|
38
|
+
it "defines index with expression as column option" do
|
39
|
+
define_schema do
|
40
|
+
create_table :users do |t|
|
41
|
+
t.string :login, index: { expression: "upper(login)" }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
expect(User.indexes.first.expression).to eq("upper((login)::text)")
|
45
|
+
expect(User.indexes.first.name).to eq("index_users_on_login")
|
46
|
+
expect(User.indexes.first.columns).to be_empty
|
47
|
+
end
|
48
|
+
|
49
|
+
it "defines multi-column index with expression as column option" do
|
50
|
+
define_schema do
|
51
|
+
create_table :users do |t|
|
52
|
+
t.string :name
|
53
|
+
t.string :login, index: { with: "name", expression: "upper(login)" }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
expect(User.indexes.first.expression).to eq("upper((login)::text)")
|
57
|
+
expect(User.indexes.first.name).to eq("index_users_on_login_and_name")
|
58
|
+
expect(User.indexes.first.columns).to eq(["name"])
|
59
|
+
end
|
60
|
+
|
61
|
+
it "defines multi-column index with column option expression that doesn't reference column" do
|
62
|
+
define_schema do
|
63
|
+
create_table :users do |t|
|
64
|
+
t.string :name
|
65
|
+
t.string :login, index: { expression: "upper(name)" }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
expect(User.indexes.first.expression).to eq("upper((name)::text)")
|
69
|
+
expect(User.indexes.first.name).to eq("index_users_on_login")
|
70
|
+
expect(User.indexes.first.columns).to eq(["login"])
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context "change table" do
|
75
|
+
it "defines index with expression only" do
|
76
|
+
define_schema do
|
77
|
+
create_table :users, :force => true do |t|
|
78
|
+
t.string :login
|
79
|
+
end
|
80
|
+
change_table :users do |t|
|
81
|
+
t.index :expression => "upper(login)", name: "no_column"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
expect(User.indexes.first.expression).to eq("upper((login)::text)")
|
85
|
+
expect(User.indexes.first.name).to eq("no_column")
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: schema_plus_pg_indexes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ronen barzel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -159,6 +159,7 @@ files:
|
|
159
159
|
- spec/index_spec.rb
|
160
160
|
- spec/named_schema_spec.rb
|
161
161
|
- spec/schema_dumper_spec.rb
|
162
|
+
- spec/schema_spec.rb
|
162
163
|
- spec/spec_helper.rb
|
163
164
|
- spec/support/matchers/have_index.rb
|
164
165
|
homepage: https://github.com/SchemaPlus/schema_plus_pg_indexes
|
@@ -192,5 +193,6 @@ test_files:
|
|
192
193
|
- spec/index_spec.rb
|
193
194
|
- spec/named_schema_spec.rb
|
194
195
|
- spec/schema_dumper_spec.rb
|
196
|
+
- spec/schema_spec.rb
|
195
197
|
- spec/spec_helper.rb
|
196
198
|
- spec/support/matchers/have_index.rb
|