cequel 2.1.0 → 3.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +2 -2
- data/README.md +8 -0
- data/lib/cequel/errors.rb +2 -0
- data/lib/cequel/metal/new_relic_instrumentation.rb +2 -1
- data/lib/cequel/record.rb +8 -0
- data/lib/cequel/record/schema.rb +30 -23
- data/lib/cequel/schema.rb +3 -2
- data/lib/cequel/schema/column.rb +11 -1
- data/lib/cequel/schema/keyspace.rb +18 -7
- data/lib/cequel/schema/patch.rb +152 -0
- data/lib/cequel/schema/table.rb +55 -137
- data/lib/cequel/schema/table_desc_dsl.rb +196 -0
- data/lib/cequel/schema/table_differ.rb +112 -0
- data/lib/cequel/schema/table_property.rb +14 -0
- data/lib/cequel/schema/table_reader.rb +81 -85
- data/lib/cequel/schema/table_updater.rb +0 -17
- data/lib/cequel/schema/table_writer.rb +10 -9
- data/lib/cequel/version.rb +1 -1
- data/spec/examples/metal/data_set_spec.rb +156 -153
- data/spec/examples/metal/keyspace_spec.rb +4 -4
- data/spec/examples/record/associations_spec.rb +6 -0
- data/spec/examples/record/mass_assignment_spec.rb +2 -2
- data/spec/examples/record/properties_spec.rb +1 -0
- data/spec/examples/record/record_set_spec.rb +1 -1
- data/spec/examples/schema/patch_spec.rb +190 -0
- data/spec/examples/schema/table_differ_spec.rb +280 -0
- data/spec/examples/schema/table_reader_spec.rb +379 -354
- data/spec/examples/schema/table_updater_spec.rb +0 -12
- data/spec/examples/spec_helper.rb +5 -5
- data/spec/examples/spec_support/preparation_spec.rb +4 -0
- data/spec/support/helpers.rb +23 -0
- metadata +9 -6
- data/lib/cequel/schema/create_table_dsl.rb +0 -88
- data/lib/cequel/schema/table_synchronizer.rb +0 -180
- data/spec/examples/schema/table_synchronizer_spec.rb +0 -200
@@ -86,17 +86,17 @@ describe Cequel::Metal::Keyspace do
|
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
89
|
-
describe "#drop_table",
|
89
|
+
describe "#drop_table", cql: "~> 3.1" do
|
90
90
|
it "allows IF EXISTS" do
|
91
91
|
expect { cequel.schema.drop_table(:unknown) }.to raise_error(Cassandra::Errors::InvalidError)
|
92
|
-
expect { cequel.schema.drop_table(:unknown, exists: true) }.not_to raise_error
|
92
|
+
expect { cequel.schema.drop_table(:unknown, exists: true) }.not_to raise_error
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
|
-
describe "#drop_materialized_view",
|
96
|
+
describe "#drop_materialized_view", cql: "~> 3.4" do
|
97
97
|
it "allows IF EXISTS" do
|
98
98
|
expect { cequel.schema.drop_materialized_view(:unknown) }.to raise_error(Cassandra::Errors::ConfigurationError)
|
99
|
-
expect { cequel.schema.drop_materialized_view(:unknown, exists: true) }.not_to raise_error
|
99
|
+
expect { cequel.schema.drop_materialized_view(:unknown, exists: true) }.not_to raise_error
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
@@ -104,6 +104,7 @@ describe Cequel::Record::Associations do
|
|
104
104
|
expect do
|
105
105
|
Class.new do
|
106
106
|
include Cequel::Record
|
107
|
+
self.table_name = "foo"
|
107
108
|
key :permalink, :text
|
108
109
|
belongs_to :blog
|
109
110
|
end
|
@@ -114,6 +115,7 @@ describe Cequel::Record::Associations do
|
|
114
115
|
expect do
|
115
116
|
Class.new do
|
116
117
|
include Cequel::Record
|
118
|
+
self.table_name = "foo"
|
117
119
|
belongs_to :blog
|
118
120
|
belongs_to :user
|
119
121
|
end
|
@@ -169,6 +171,8 @@ describe Cequel::Record::Associations do
|
|
169
171
|
expect do
|
170
172
|
Class.new do
|
171
173
|
include Cequel::Record
|
174
|
+
self.table_name = "foo"
|
175
|
+
|
172
176
|
key :permalink, :text
|
173
177
|
belongs_to :post, partition: true
|
174
178
|
end
|
@@ -179,6 +183,8 @@ describe Cequel::Record::Associations do
|
|
179
183
|
expect do
|
180
184
|
Class.new do
|
181
185
|
include Cequel::Record
|
186
|
+
self.table_name = "foo"
|
187
|
+
|
182
188
|
belongs_to :post, partition: true
|
183
189
|
belongs_to :user
|
184
190
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
require_relative 'spec_helper'
|
3
3
|
|
4
4
|
describe Cequel::Record::MassAssignment do
|
5
|
-
context 'with strong parameters', :
|
5
|
+
context 'with strong parameters', rails: '>= 4.0' do
|
6
6
|
model :Post do
|
7
7
|
key :permalink, :text
|
8
8
|
column :title, :text
|
@@ -34,7 +34,7 @@ describe Cequel::Record::MassAssignment do
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
context 'with mass-assignment protection', :
|
37
|
+
context 'with mass-assignment protection', rails: '~> 3.0' do
|
38
38
|
model :Post do
|
39
39
|
key :permalink, :text
|
40
40
|
column :title, :text
|
@@ -806,7 +806,7 @@ describe Cequel::Record::RecordSet do
|
|
806
806
|
end
|
807
807
|
end
|
808
808
|
|
809
|
-
context 'allow_filtering!',
|
809
|
+
context 'allow_filtering!', cql: '~> 3.4' do
|
810
810
|
it 'should allow filtering for none indexed columns' do
|
811
811
|
expect(Post.allow_filtering!.where(title: 'Cequel 0').entries.length).to be(1)
|
812
812
|
end
|
@@ -0,0 +1,190 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
3
|
+
|
4
|
+
module Cequel::Schema
|
5
|
+
describe Patch do
|
6
|
+
|
7
|
+
let(:table_name) { |ex| unique_table_name("posts", ex) }
|
8
|
+
let(:table) {
|
9
|
+
Table.new(table_name).tap do |t|
|
10
|
+
t.add_column PartitionKey.new(:blog_subdomain, Cequel::Type[:text])
|
11
|
+
end
|
12
|
+
}
|
13
|
+
|
14
|
+
describe ".new" do
|
15
|
+
it "returns a Patch" do
|
16
|
+
expect(
|
17
|
+
described_class.new([])
|
18
|
+
).to be_kind_of described_class
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#changes" do
|
23
|
+
context "no changes" do
|
24
|
+
subject { described_class.new([]) }
|
25
|
+
|
26
|
+
it "returns the changes" do
|
27
|
+
expect( subject.changes ).to be_empty
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "no some changes" do
|
32
|
+
let(:change) {
|
33
|
+
Patch::AddColumn.new(table, DataColumn.new(:author_name, Cequel::Type[:text]))
|
34
|
+
}
|
35
|
+
|
36
|
+
subject { described_class.new([change]) }
|
37
|
+
|
38
|
+
it "returns the changes" do
|
39
|
+
expect( subject.changes ).to eq [change]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#statements" do
|
45
|
+
let(:change) {
|
46
|
+
Patch::AddColumn.new(table, DataColumn.new(:author_name, Cequel::Type[:text]))
|
47
|
+
}
|
48
|
+
|
49
|
+
subject { described_class.new([change]) }
|
50
|
+
|
51
|
+
it "returns a statement for each change" do
|
52
|
+
expect( subject.statements.count ).to eq subject.changes.count
|
53
|
+
expect( subject.statements.count ).to eq 1
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe Patch::SetTableProperties do
|
59
|
+
let(:table_name) { |ex| unique_table_name("posts", ex) }
|
60
|
+
let(:table) {
|
61
|
+
Table.new(table_name).tap do |t|
|
62
|
+
t.add_property TableProperty.build(:comment, "hello")
|
63
|
+
end
|
64
|
+
}
|
65
|
+
|
66
|
+
describe "#new" do
|
67
|
+
it "returns #{described_class}" do
|
68
|
+
expect( described_class.new(table) ).to be_kind_of described_class
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
subject { described_class.new(table) }
|
73
|
+
|
74
|
+
describe "#to_cql" do
|
75
|
+
it "sets the property" do
|
76
|
+
expect( subject.to_cql ).to match /alter +table +"?#{table_name}"? +with/i
|
77
|
+
expect( subject.to_cql ).to match /"?comment"? *= *'hello'/i
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#properties" do
|
82
|
+
it "returns collection of Table properties to be set" do
|
83
|
+
expect( subject.properties ).to all be_kind_of TableProperty
|
84
|
+
expect( subject.properties ).to eq table.properties.values
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe Patch::DropIndex do
|
91
|
+
let(:table_name) { |ex| unique_table_name("posts", ex) }
|
92
|
+
let(:table) { Table.new(table_name) }
|
93
|
+
let(:column_with_obsolete_idx) {
|
94
|
+
DataColumn.new(:author_name, Cequel::Type[:text], :author_name_idx)
|
95
|
+
}
|
96
|
+
|
97
|
+
describe "#new" do
|
98
|
+
it "returns #{described_class}" do
|
99
|
+
expect(
|
100
|
+
described_class.new(table, column_with_obsolete_idx)
|
101
|
+
).to be_kind_of described_class
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
subject { described_class.new(table, column_with_obsolete_idx) }
|
106
|
+
|
107
|
+
describe "#to_cql" do
|
108
|
+
it "drops index" do
|
109
|
+
expect( subject.to_cql ).to match /drop +index/i
|
110
|
+
expect( subject.to_cql ).to match /"?#{column_with_obsolete_idx.index_name}"?/i
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "#index_name" do
|
115
|
+
it "returns the index name" do
|
116
|
+
expect( subject.index_name ).to eq column_with_obsolete_idx.index_name
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe Patch::AddIndex do
|
122
|
+
let(:table_name) { |ex| unique_table_name("posts", ex) }
|
123
|
+
let(:table) { Table.new(table_name) }
|
124
|
+
let(:column) {
|
125
|
+
DataColumn.new(:author_name, Cequel::Type[:text], :author_name_idx)
|
126
|
+
}
|
127
|
+
|
128
|
+
describe "#new" do
|
129
|
+
it "returns #{described_class}" do
|
130
|
+
expect(
|
131
|
+
described_class.new(table, column)
|
132
|
+
).to be_kind_of described_class
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
subject { described_class.new(table, column) }
|
137
|
+
|
138
|
+
describe "#to_cql" do
|
139
|
+
it "creates the index" do
|
140
|
+
expect( subject.to_cql ).to match /create +index/i
|
141
|
+
expect( subject.to_cql ).to match /"#{column.index_name}"/i
|
142
|
+
expect( subject.to_cql ).to match /( *"#{column.name}" *)/i
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
describe "#index_name" do
|
147
|
+
it "returns the index name" do
|
148
|
+
expect( subject.index_name ).to eq column.index_name
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
describe "#column" do
|
153
|
+
it "returns the column" do
|
154
|
+
expect( subject.column ).to eq column
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe Patch::AddColumn do
|
160
|
+
let(:table_name) { |ex| unique_table_name("posts", ex) }
|
161
|
+
let(:table) { Table.new(table_name) }
|
162
|
+
let(:column) {
|
163
|
+
DataColumn.new(:author_name, Cequel::Type[:text])
|
164
|
+
}
|
165
|
+
|
166
|
+
describe "#new" do
|
167
|
+
it "returns #{described_class}" do
|
168
|
+
expect(
|
169
|
+
described_class.new(table, column)
|
170
|
+
).to be_kind_of described_class
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
subject { described_class.new(table, column) }
|
175
|
+
|
176
|
+
describe "#to_cql" do
|
177
|
+
it "adds the column" do
|
178
|
+
expect( subject.to_cql ).to match /alter +table/i
|
179
|
+
expect( subject.to_cql ).to match /"#{table_name}"/i
|
180
|
+
expect( subject.to_cql ).to match /add +"#{column.name}"/i
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe "#column" do
|
185
|
+
it "returns the column" do
|
186
|
+
expect( subject.column ).to eq column
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
@@ -0,0 +1,280 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
3
|
+
|
4
|
+
module Cequel::Schema
|
5
|
+
describe TableDiffer do
|
6
|
+
|
7
|
+
let(:table_name) { |ex| unique_table_name("posts", ex) }
|
8
|
+
let(:orig_table) {
|
9
|
+
Table.new(table_name).tap do |t|
|
10
|
+
t.add_column PartitionKey.new(:blog_subdomain, Cequel::Type[:text])
|
11
|
+
t.add_column ClusteringColumn.new(:slug, Cequel::Type[:text])
|
12
|
+
t.add_column DataColumn.new(:body, Cequel::Type[:text])
|
13
|
+
t.add_column DataColumn.new(:author_name, Cequel::Type[:text], :author_name_idx)
|
14
|
+
t.add_property TableProperty.build(:comment, "Orig comment")
|
15
|
+
end
|
16
|
+
}
|
17
|
+
|
18
|
+
describe ".new" do
|
19
|
+
it "returns a TableDiffer" do
|
20
|
+
expect(
|
21
|
+
described_class.new(orig_table, orig_table)
|
22
|
+
).to be_kind_of described_class
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe ".call" do
|
27
|
+
it "returns a Patch" do
|
28
|
+
updated_table = Table.new(table_name).tap do |t|
|
29
|
+
t.add_column PartitionKey.new(:blog_subdomain, Cequel::Type[:text])
|
30
|
+
t.add_column ClusteringColumn.new(:slug, Cequel::Type[:text])
|
31
|
+
t.add_column DataColumn.new(:body, Cequel::Type[:text])
|
32
|
+
t.add_column DataColumn.new(:author_name, Cequel::Type[:text], :author_name_idx)
|
33
|
+
t.add_property TableProperty.build(:comment, "Orig comment")
|
34
|
+
end
|
35
|
+
|
36
|
+
expect(
|
37
|
+
described_class.new(orig_table, updated_table).call
|
38
|
+
).to be_kind_of Patch
|
39
|
+
end
|
40
|
+
|
41
|
+
it "fails for table name changes" do
|
42
|
+
renamed_table = Table.new(:fancy_new_name).tap do |t|
|
43
|
+
t.add_column PartitionKey.new(:blog_subdomain, Cequel::Type[:text])
|
44
|
+
t.add_column ClusteringColumn.new(:slug, Cequel::Type[:text])
|
45
|
+
t.add_column DataColumn.new(:body, Cequel::Type[:text])
|
46
|
+
t.add_column DataColumn.new(:author_name, Cequel::Type[:text], :author_name_idx)
|
47
|
+
t.add_property TableProperty.build(:comment, "Orig comment")
|
48
|
+
end
|
49
|
+
|
50
|
+
expect{
|
51
|
+
described_class.new(orig_table, renamed_table).call
|
52
|
+
}.to raise_error(Cequel::InvalidSchemaMigration)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "succeed if name difference it immaterial" do
|
56
|
+
equiv_table = Table.new(table_name.to_s).tap do |t|
|
57
|
+
t.add_column PartitionKey.new(:blog_subdomain, Cequel::Type[:text])
|
58
|
+
t.add_column ClusteringColumn.new(:slug, Cequel::Type[:text])
|
59
|
+
t.add_column DataColumn.new(:body, Cequel::Type[:text])
|
60
|
+
t.add_column DataColumn.new(:author_name, Cequel::Type[:text], :author_name_idx)
|
61
|
+
t.add_property TableProperty.build(:comment, "Orig comment")
|
62
|
+
end
|
63
|
+
|
64
|
+
expect{
|
65
|
+
described_class.new(orig_table, equiv_table).call
|
66
|
+
}.not_to raise_error
|
67
|
+
end
|
68
|
+
|
69
|
+
it "fails for type changes" do
|
70
|
+
updated_table = Table.new(table_name).tap do |t|
|
71
|
+
t.add_column PartitionKey.new(:blog_subdomain, Cequel::Type[:text])
|
72
|
+
t.add_column ClusteringColumn.new(:slug, Cequel::Type[:text])
|
73
|
+
t.add_column DataColumn.new(:body, Cequel::Type[:ascii])
|
74
|
+
end
|
75
|
+
|
76
|
+
expect{
|
77
|
+
described_class.new(orig_table, updated_table).call
|
78
|
+
}.to raise_error(Cequel::InvalidSchemaMigration)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "fails for partition key changes" do
|
82
|
+
updated_table = Table.new(table_name).tap do |t|
|
83
|
+
t.add_column PartitionKey.new(:blog_subdomain, Cequel::Type[:text])
|
84
|
+
t.add_column PartitionKey.new(:date, Cequel::Type[:timestamp])
|
85
|
+
t.add_column ClusteringColumn.new(:slug, Cequel::Type[:text])
|
86
|
+
t.add_column DataColumn.new(:body, Cequel::Type[:text])
|
87
|
+
t.add_column DataColumn.new(:author_name, Cequel::Type[:text], :author_name_idx)
|
88
|
+
t.add_property TableProperty.build(:comment, "Orig comment")
|
89
|
+
end
|
90
|
+
|
91
|
+
expect{
|
92
|
+
described_class.new(orig_table, updated_table).call
|
93
|
+
}.to raise_error(Cequel::InvalidSchemaMigration)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "fails for clustering order changes" do
|
97
|
+
updated_table = Table.new(table_name).tap do |t|
|
98
|
+
t.add_column PartitionKey.new(:blog_subdomain, Cequel::Type[:text])
|
99
|
+
t.add_column ClusteringColumn.new(:slug, Cequel::Type[:text], :desc)
|
100
|
+
t.add_column DataColumn.new(:body, Cequel::Type[:text])
|
101
|
+
t.add_column DataColumn.new(:author_name, Cequel::Type[:text], :author_name_idx)
|
102
|
+
t.add_property TableProperty.build(:comment, "Orig comment")
|
103
|
+
end
|
104
|
+
|
105
|
+
expect{
|
106
|
+
described_class.new(orig_table, updated_table).call
|
107
|
+
}.to raise_error(Cequel::InvalidSchemaMigration)
|
108
|
+
end
|
109
|
+
|
110
|
+
it "ignore immaterial changes to clustering order" do
|
111
|
+
unchanged_table = Table.new(table_name).tap do |t|
|
112
|
+
t.add_column PartitionKey.new(:blog_subdomain, Cequel::Type[:text])
|
113
|
+
t.add_column ClusteringColumn.new(:slug, Cequel::Type[:text], :asc)
|
114
|
+
t.add_column DataColumn.new(:body, Cequel::Type[:text])
|
115
|
+
t.add_column DataColumn.new(:author_name, Cequel::Type[:text], :author_name_idx)
|
116
|
+
t.add_property TableProperty.build(:comment, "Orig comment")
|
117
|
+
end
|
118
|
+
|
119
|
+
expect{
|
120
|
+
described_class.new(orig_table, unchanged_table).call
|
121
|
+
}.not_to raise_error
|
122
|
+
end
|
123
|
+
|
124
|
+
it "detects a lack of changes changes" do
|
125
|
+
unchanged_table = Table.new(table_name).tap do |t|
|
126
|
+
t.add_column PartitionKey.new(:blog_subdomain, Cequel::Type[:text])
|
127
|
+
t.add_column ClusteringColumn.new(:slug, Cequel::Type[:text])
|
128
|
+
t.add_column DataColumn.new(:body, Cequel::Type[:text])
|
129
|
+
t.add_column DataColumn.new(:author_name, Cequel::Type[:text], :author_name_idx)
|
130
|
+
t.add_property TableProperty.build(:comment, "Orig comment")
|
131
|
+
end
|
132
|
+
|
133
|
+
expect(
|
134
|
+
described_class.new(orig_table, unchanged_table).call
|
135
|
+
).to be_empty
|
136
|
+
end
|
137
|
+
|
138
|
+
it "detects new columns" do
|
139
|
+
updated_table = Table.new(table_name).tap do |t|
|
140
|
+
t.add_column PartitionKey.new(:blog_subdomain, Cequel::Type[:text])
|
141
|
+
t.add_column ClusteringColumn.new(:slug, Cequel::Type[:text])
|
142
|
+
t.add_column DataColumn.new(:body, Cequel::Type[:text])
|
143
|
+
t.add_column DataColumn.new(:created_at, Cequel::Type[:timestamp])
|
144
|
+
end
|
145
|
+
|
146
|
+
expect(
|
147
|
+
described_class.new(orig_table, updated_table).call
|
148
|
+
).to add_column(:created_at).of_type(:timestamp)
|
149
|
+
end
|
150
|
+
|
151
|
+
it "detects added index to existing column" do
|
152
|
+
updated_table = Table.new(table_name).tap do |t|
|
153
|
+
t.add_column PartitionKey.new(:blog_subdomain, Cequel::Type[:text])
|
154
|
+
t.add_column ClusteringColumn.new(:slug, Cequel::Type[:text])
|
155
|
+
t.add_column DataColumn.new(:body, Cequel::Type[:text], :my_index_name)
|
156
|
+
end
|
157
|
+
|
158
|
+
expect(
|
159
|
+
described_class.new(orig_table, updated_table).call
|
160
|
+
).to add_index(:my_index_name).of_column(:body)
|
161
|
+
end
|
162
|
+
|
163
|
+
it "detects dropped index" do
|
164
|
+
updated_table = Table.new(table_name).tap do |t|
|
165
|
+
t.add_column PartitionKey.new(:blog_subdomain, Cequel::Type[:text])
|
166
|
+
t.add_column ClusteringColumn.new(:slug, Cequel::Type[:text])
|
167
|
+
t.add_column DataColumn.new(:body, Cequel::Type[:text])
|
168
|
+
t.add_column DataColumn.new(:author_name, Cequel::Type[:text])
|
169
|
+
end
|
170
|
+
|
171
|
+
expect(
|
172
|
+
described_class.new(orig_table, updated_table).call
|
173
|
+
).to drop_index(:author_name_idx)
|
174
|
+
end
|
175
|
+
|
176
|
+
it "detects added index to new column" do
|
177
|
+
updated_table = Table.new(table_name).tap do |t|
|
178
|
+
t.add_column PartitionKey.new(:blog_subdomain, Cequel::Type[:text])
|
179
|
+
t.add_column ClusteringColumn.new(:slug, Cequel::Type[:text])
|
180
|
+
t.add_column DataColumn.new(:category, Cequel::Type[:text], :posts_category_idx)
|
181
|
+
end
|
182
|
+
|
183
|
+
expect(
|
184
|
+
described_class.new(orig_table, updated_table).call
|
185
|
+
).to add_index(:posts_category_idx).of_column(:category)
|
186
|
+
end
|
187
|
+
|
188
|
+
it "ignores dropped columns" do
|
189
|
+
updated_table = Table.new(table_name).tap do |t|
|
190
|
+
t.add_column PartitionKey.new(:blog_subdomain, Cequel::Type[:text])
|
191
|
+
t.add_column ClusteringColumn.new(:slug, Cequel::Type[:text])
|
192
|
+
t.add_column DataColumn.new(:body, Cequel::Type[:text])
|
193
|
+
t.add_property TableProperty.build(:comment, "Orig comment")
|
194
|
+
end
|
195
|
+
|
196
|
+
expect(
|
197
|
+
described_class.new(orig_table, updated_table).call
|
198
|
+
).to be_empty
|
199
|
+
end
|
200
|
+
|
201
|
+
it "detects new property" do
|
202
|
+
updated_table = Table.new(table_name).tap do |t|
|
203
|
+
t.add_column PartitionKey.new(:blog_subdomain, Cequel::Type[:text])
|
204
|
+
t.add_column ClusteringColumn.new(:slug, Cequel::Type[:text])
|
205
|
+
t.add_property TableProperty.build(:comment, "test")
|
206
|
+
end
|
207
|
+
|
208
|
+
expect(
|
209
|
+
described_class.new(orig_table, updated_table).call
|
210
|
+
).to set_property(:comment, "test")
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
# Background
|
215
|
+
|
216
|
+
matcher :set_property do |expected_name, expected_val|
|
217
|
+
match do |actual_patch|
|
218
|
+
actual_patch.changes
|
219
|
+
.any? { |actual_change|
|
220
|
+
actual_change.is_a?(Cequel::Schema::Patch::SetTableProperties) &&
|
221
|
+
actual_change.properties
|
222
|
+
.any?{|p|
|
223
|
+
p.name.to_s == expected_name.to_s &&
|
224
|
+
expected_val === p.value
|
225
|
+
}
|
226
|
+
}
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
matcher :drop_index do |index_name|
|
231
|
+
match do |actual_patch|
|
232
|
+
actual_patch.changes
|
233
|
+
.any? { |actual_change|
|
234
|
+
actual_change.is_a?(Cequel::Schema::Patch::DropIndex) &&
|
235
|
+
actual_change.index_name.to_s == index_name.to_s
|
236
|
+
}
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
matcher :add_index do |index_name|
|
241
|
+
@column_matcher = ->(_){true}
|
242
|
+
|
243
|
+
match do |actual_patch|
|
244
|
+
actual_patch.changes
|
245
|
+
.any? { |actual_change|
|
246
|
+
actual_change.is_a?(Cequel::Schema::Patch::AddIndex) &&
|
247
|
+
@column_matcher === actual_change.column &&
|
248
|
+
actual_change.index_name.to_s == index_name.to_s
|
249
|
+
}
|
250
|
+
end
|
251
|
+
|
252
|
+
chain :of_column do |col_name|
|
253
|
+
@column_matcher = ->(col) { col.name.to_s == col_name.to_s }
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
matcher :add_column do |name|
|
258
|
+
@type_matcher = ->(_){true}
|
259
|
+
|
260
|
+
match do |actual_patch|
|
261
|
+
actual_patch.changes
|
262
|
+
.any? { |actual_change|
|
263
|
+
actual_change.is_a?(Cequel::Schema::Patch::AddColumn) &&
|
264
|
+
actual_change.column.name == name &&
|
265
|
+
@type_matcher === actual_change.column.type
|
266
|
+
}
|
267
|
+
end
|
268
|
+
|
269
|
+
chain :of_type do |type_or_matcher|
|
270
|
+
@type_matcher = if type_or_matcher.respond_to?(:call)
|
271
|
+
type_or_matcher
|
272
|
+
elsif t = Cequel::Type[type_or_matcher]
|
273
|
+
->(type) { type == t }
|
274
|
+
else
|
275
|
+
fail "unsupported type matcher: #{type_or_matcher.inspect}"
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|