schema_plus_pg_indexes 0.1.6 → 0.1.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 809e25804e94035df8d24a57d5a255c8d64c8eb8
4
- data.tar.gz: 92e7716fb86ece5c7f420b22ce6a75cfd36f3677
3
+ metadata.gz: 23c0466d72bdac73b797047b1b0db33bbb840672
4
+ data.tar.gz: 51c899f934b0d2b480d63e2759b4b9d148b3351d
5
5
  SHA512:
6
- metadata.gz: ef0acdf61aeda8a0c6980dba96ccbdb4357f7719476238742700cae71d83d757230b44bf19c353cc468a4ea1e479b1d4b1814e4b75911fcd3876b126af6b331f
7
- data.tar.gz: 2bd3c3b3fb713678d041633c833c7c791e3a9d6909c2b714ce9197105471c38da4dbfcd00c38c90a9c014848a6f21dda7c61d92a05906bf12e16554fa9e9874b
6
+ metadata.gz: e1690a53c5d96bbdfa7f5a33a12db3a91f72c59c3907bee9908f1556bc83eaaa2c629080ac5ed5c9ee57989094fb27d63e43b40b70574b88e65bc13cc4ea1ce1
7
+ data.tar.gz: b5fc2d3442f501ec154f79f8f2a0d018ca667ea11e266df1232fe2a45be825d3989234c540f31a60366009aaaf20c8e3fdda96f0bfb0a967bdf1bdeba64cc743
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.7 - Bug fix: mix of columns & expressions (#5)
64
65
  * v0.1.6 - Bug fix: operator class & multiple columns (#4). Thanks to [@nbudin](https://github.com/nbudin)
65
66
  * v0.1.5 - Bug fix: `t.index` without column in `change_table`
66
67
  * v0.1.1 through v0.1.4 - Conform to schema_dev updates
@@ -11,16 +11,13 @@ module SchemaPlusPgIndexes
11
11
 
12
12
  env.table.indexes.each do |index_dump|
13
13
  index_def = index_defs.find(&its.name == index_dump.name)
14
- if index_def.columns.blank?
15
- index_dump.add_option "expression: #{index_def.expression.inspect}" if index_def.expression and index_def.columns.blank?
16
- else
17
- index_dump.add_option "case_sensitive: false" unless index_def.case_sensitive?
18
- unless index_def.operator_classes.blank?
19
- if index_def.columns.uniq.length == 1 && index_def.operator_classes.values.uniq.length == 1
20
- index_dump.add_option "operator_class: #{index_def.operator_classes.values.first.inspect}"
21
- else
22
- index_dump.add_option "operator_class: {" + index_def.operator_classes.map{|column, val| "#{column.inspect}=>#{val.inspect}"}.join(", ") + "}"
23
- end
14
+ index_dump.add_option "case_sensitive: false" unless index_def.case_sensitive?
15
+ index_dump.add_option "expression: #{index_def.expression.inspect}" if index_def.expression and index_def.case_sensitive?
16
+ unless index_def.operator_classes.blank?
17
+ if index_def.columns.uniq.length == 1 && index_def.operator_classes.values.uniq.length == 1
18
+ index_dump.add_option "operator_class: #{index_def.operator_classes.values.first.inspect}"
19
+ else
20
+ index_dump.add_option "operator_class: {" + index_def.operator_classes.map{|column, val| "#{column.inspect}=>#{val.inspect}"}.join(", ") + "}"
24
21
  end
25
22
  end
26
23
  end
@@ -76,13 +76,13 @@ module SchemaPlusPgIndexes
76
76
  # only applies to character, character varying, and text
77
77
  if expression
78
78
  rexp_lower = %r{\blower\(\(?([^)]+)(\)::text)?\)}
79
- if expression.match /\A#{rexp_lower}(?:, #{rexp_lower})*\z/
79
+ if expression.match /\A#{rexp_lower}(?:, #{rexp_lower})*\z/i
80
80
  case_insensitive_columns = expression.scan(rexp_lower).map(&:first).select{|column| %W[char varchar text].include? types[column]}
81
81
  if case_insensitive_columns.any?
82
82
  case_sensitive = false
83
83
  column_names = index_keys.map { |index_key|
84
84
  index_key == '0' ? case_insensitive_columns.shift : columns[index_key]
85
- }.compact
85
+ }.compact | column_names
86
86
  end
87
87
  end
88
88
  end
@@ -52,9 +52,7 @@ module SchemaPlusPgIndexes
52
52
  operator_classes = Hash[column_names.map {|name| [name, operator_classes]}]
53
53
  end
54
54
 
55
- if expression
56
- env.sql.columns = expression
57
- elsif operator_classes or case_insensitive
55
+ if operator_classes or case_insensitive
58
56
  option_strings = Hash[column_names.map {|name| [name, '']}]
59
57
  (operator_classes||{}).stringify_keys.each do |column, opclass|
60
58
  option_strings[column] += " #{opclass}" if opclass
@@ -72,6 +70,10 @@ module SchemaPlusPgIndexes
72
70
 
73
71
  env.sql.columns = quoted_column_names.join(', ')
74
72
  end
73
+
74
+ if expression
75
+ env.sql.columns = (env.sql.columns.split(/ *, */).reject{|col| expression =~ %r{\b#{col.gsub(/['"]/, '')}\b} } + [expression]).join(', ')
76
+ end
75
77
  end
76
78
  end
77
79
  end
@@ -1,3 +1,3 @@
1
1
  module SchemaPlusPgIndexes
2
- VERSION = "0.1.6"
2
+ VERSION = "0.1.7"
3
3
  end
@@ -5,7 +5,7 @@ describe "Index definition" do
5
5
 
6
6
  let(:migration) { ::ActiveRecord::Migration }
7
7
 
8
- before(:all) do
8
+ before(:each) do
9
9
  define_schema do
10
10
  create_table :users, :force => true do |t|
11
11
  t.string :login
@@ -23,16 +23,6 @@ describe "Index definition" do
23
23
  class Post < ::ActiveRecord::Base ; end
24
24
  end
25
25
 
26
- around(:each) do |example|
27
- migration.suppress_messages do
28
- example.run
29
- end
30
- end
31
-
32
- after(:each) do
33
- migration.remove_index :users, :name => 'users_login_index' if migration.index_name_exists? :users, 'users_login_index', true
34
- end
35
-
36
26
  context "when case insensitive is added" do
37
27
 
38
28
  before(:each) do
@@ -60,7 +50,7 @@ describe "Index definition" do
60
50
  end
61
51
 
62
52
 
63
- context "when index contains expression" do
53
+ context "when index contains an expression" do
64
54
  before(:each) do
65
55
  migration.execute "CREATE INDEX users_login_index ON users (extract(EPOCH from deleted_at)) WHERE deleted_at IS NULL"
66
56
  User.reset_column_information
@@ -89,6 +79,35 @@ describe "Index definition" do
89
79
 
90
80
  end
91
81
 
82
+ context "when index contains mix of expressions and columns" do
83
+ before(:each) do
84
+ define_schema do
85
+ create_table :users, :force => true do |t|
86
+ t.string :alpha
87
+ t.string :beta
88
+ t.string :gamma
89
+ t.string :delta
90
+ end
91
+ execute "CREATE INDEX multi ON users (alpha, (upper(beta)), gamma, (upper(delta)))"
92
+ end
93
+ User.reset_column_information
94
+ @index = User.indexes.detect { |i| i.expression.present? }
95
+ end
96
+
97
+ it "exists" do
98
+ expect(@index).not_to be_nil
99
+ end
100
+
101
+ it "havs columns defined" do
102
+ expect(@index.columns).to eq(["alpha", "gamma"])
103
+ end
104
+
105
+ it "defines expression" do
106
+ expect(@index.expression).to eq("upper((beta)::text), upper((delta)::text)")
107
+ end
108
+
109
+ end
110
+
92
111
  context "when index has a non-btree type" do
93
112
  before(:each) do
94
113
  migration.execute "CREATE INDEX users_login_index ON users USING hash(login)"
@@ -21,10 +21,8 @@ describe "index" do
21
21
  context "extra features" do
22
22
 
23
23
  before(:each) do
24
- connection.tables.each do |table| connection.drop_table table, cascade: true end
25
-
26
24
  define_schema do
27
- create_table :users, :force => true do |t|
25
+ create_table :users do |t|
28
26
  t.string :login
29
27
  t.text :address
30
28
  t.jsonb :json_col
@@ -88,7 +86,7 @@ describe "index" do
88
86
  context "create table" do
89
87
  it "defines index with expression only" do
90
88
  define_schema do
91
- create_table :users, :force => true do |t|
89
+ create_table :users do |t|
92
90
  t.string :login
93
91
  t.index :expression => "upper(login)", name: "no_column"
94
92
  end
@@ -96,6 +94,41 @@ describe "index" do
96
94
  expect(User.indexes.first.expression).to eq("upper((login)::text)")
97
95
  expect(User.indexes.first.name).to eq("no_column")
98
96
  end
97
+
98
+ it "defines index with expression as column option" do
99
+ define_schema do
100
+ create_table :users do |t|
101
+ t.string :login, index: { expression: "upper(login)" }
102
+ end
103
+ end
104
+ expect(User.indexes.first.expression).to eq("upper((login)::text)")
105
+ expect(User.indexes.first.name).to eq("index_users_on_login")
106
+ expect(User.indexes.first.columns).to be_empty
107
+ end
108
+
109
+ it "defines multi-column index with expression as column option" do
110
+ define_schema do
111
+ create_table :users do |t|
112
+ t.string :name
113
+ t.string :login, index: { with: "name", expression: "upper(login)" }
114
+ end
115
+ end
116
+ expect(User.indexes.first.expression).to eq("upper((login)::text)")
117
+ expect(User.indexes.first.name).to eq("index_users_on_login_and_name")
118
+ expect(User.indexes.first.columns).to eq(["name"])
119
+ end
120
+
121
+ it "defines multi-column index with column option expression that doesn't reference column" do
122
+ define_schema do
123
+ create_table :users do |t|
124
+ t.string :name
125
+ t.string :login, index: { expression: "upper(name)" }
126
+ end
127
+ end
128
+ expect(User.indexes.first.expression).to eq("upper((name)::text)")
129
+ expect(User.indexes.first.name).to eq("index_users_on_login")
130
+ expect(User.indexes.first.columns).to eq(["login"])
131
+ end
99
132
  end
100
133
 
101
134
  context "change table" do
@@ -3,18 +3,18 @@ require 'stringio'
3
3
 
4
4
  describe "Schema dump" do
5
5
 
6
- before(:all) do
6
+ before(:each) do
7
7
  ActiveRecord::Migration.suppress_messages do
8
8
  ActiveRecord::Schema.define do
9
9
  connection.tables.each do |table| drop_table table, force: :cascade end
10
10
 
11
- create_table :users, :force => true do |t|
11
+ create_table :users do |t|
12
12
  t.string :login
13
13
  t.datetime :deleted_at
14
14
  t.integer :first_post_id
15
15
  end
16
16
 
17
- create_table :posts, :force => true do |t|
17
+ create_table :posts do |t|
18
18
  t.text :body
19
19
  t.integer :user_id
20
20
  t.integer :first_comment_id
@@ -32,7 +32,7 @@ describe "Schema dump" do
32
32
  t.boolean :boolean_col
33
33
  end
34
34
 
35
- create_table :comments, :force => true do |t|
35
+ create_table :comments do |t|
36
36
  t.text :body
37
37
  t.integer :post_id
38
38
  t.integer :commenter_id
@@ -86,6 +86,13 @@ describe "Schema dump" do
86
86
  end
87
87
  end
88
88
 
89
+ it "should define multi-column with expression" do
90
+ with_index Post, :body, :expression => "(least(id, user_id))" do
91
+ expect(dump_posts).to match(/body.*index.*expression: "LEAST\(id, user_id\)"/)
92
+ end
93
+ end
94
+
95
+
89
96
  it "should define operator_class" do
90
97
  with_index Post, :body, :operator_class => 'text_pattern_ops' do
91
98
  expect(dump_posts).to match(/body.*index:.*operator_class: "text_pattern_ops"/)
@@ -139,13 +146,7 @@ describe "Schema dump" do
139
146
  ActiveRecord::Migration.add_index(model.table_name, columns, options)
140
147
  end
141
148
  model.reset_column_information
142
- begin
143
- yield
144
- ensure
145
- ActiveRecord::Migration.suppress_messages do
146
- ActiveRecord::Migration.remove_index(model.table_name, :name => determine_index_name(model, columns, options))
147
- end
148
- end
149
+ yield
149
150
  end
150
151
 
151
152
  def determine_index_name(model, columns, options)
@@ -17,16 +17,19 @@ Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
17
17
  RSpec.configure do |config|
18
18
  config.include(SchemaPlusPgIndexesMatchers)
19
19
  config.warnings = true
20
+ config.around(:each) do |example|
21
+ ActiveRecord::Migration.suppress_messages do
22
+ example.run
23
+ end
24
+ end
20
25
  end
21
26
 
22
27
  def define_schema(&block)
23
- ActiveRecord::Migration.suppress_messages do
24
- ActiveRecord::Schema.define do
25
- connection.tables.each do |table|
26
- drop_table table, force: :cascade
27
- end
28
- instance_eval &block
28
+ ActiveRecord::Schema.define do
29
+ connection.tables.each do |table|
30
+ drop_table table, force: :cascade
29
31
  end
32
+ instance_eval &block
30
33
  end
31
34
  end
32
35
 
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.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - ronen barzel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-30 00:00:00.000000000 Z
11
+ date: 2015-10-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord