cassanity 0.6.0.beta5 → 0.6.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/README.md +1 -0
- data/doc/Migrations.md +4 -15
- data/examples/collections.rb +82 -0
- data/lib/cassanity.rb +54 -0
- data/lib/cassanity/addition.rb +15 -0
- data/lib/cassanity/argument_generators/batch.rb +8 -1
- data/lib/cassanity/argument_generators/column_family_create.rb +11 -1
- data/lib/cassanity/argument_generators/column_family_delete.rb +19 -4
- data/lib/cassanity/argument_generators/keyspace_create.rb +5 -1
- data/lib/cassanity/argument_generators/set_clause.rb +4 -1
- data/lib/cassanity/collection_item.rb +39 -0
- data/lib/cassanity/removal.rb +15 -0
- data/lib/cassanity/schema.rb +5 -2
- data/lib/cassanity/set_addition.rb +16 -0
- data/lib/cassanity/set_removal.rb +16 -0
- data/lib/cassanity/statement.rb +4 -1
- data/lib/cassanity/version.rb +1 -1
- data/spec/unit/cassanity/addition_spec.rb +80 -0
- data/spec/unit/cassanity/argument_generators/batch_spec.rb +45 -0
- data/spec/unit/cassanity/argument_generators/column_family_create_spec.rb +20 -0
- data/spec/unit/cassanity/argument_generators/column_family_delete_spec.rb +42 -0
- data/spec/unit/cassanity/argument_generators/keyspace_create_spec.rb +11 -0
- data/spec/unit/cassanity/argument_generators/set_clause_spec.rb +35 -0
- data/spec/unit/cassanity/collection_item_spec.rb +84 -0
- data/spec/unit/cassanity/removal_spec.rb +80 -0
- data/spec/unit/cassanity/schema_spec.rb +49 -0
- data/spec/unit/cassanity/set_addition_spec.rb +80 -0
- data/spec/unit/cassanity/set_removal_spec.rb +80 -0
- data/spec/unit/cassanity/statement_spec.rb +9 -2
- data/spec/unit/cassanity_spec.rb +42 -0
- metadata +31 -15
data/lib/cassanity/statement.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'bigdecimal'
|
2
2
|
require 'date'
|
3
|
+
require 'set'
|
3
4
|
require 'time'
|
4
5
|
|
5
6
|
module Cassanity
|
@@ -19,7 +20,9 @@ module Cassanity
|
|
19
20
|
private
|
20
21
|
def quote(var)
|
21
22
|
if Array === var
|
22
|
-
var.map { |v| quote(v) }.join(',')
|
23
|
+
%([#{var.map { |v| "#{quote(v)}" }.join(',')}])
|
24
|
+
elsif Set === var
|
25
|
+
%({#{var.map { |v| "#{quote(v)}" }.join(',')}})
|
23
26
|
elsif Hash === var
|
24
27
|
%({#{var.map { |k, v| "#{quote(k)}:#{quote(v)}" }.join(',')}})
|
25
28
|
elsif String === var
|
data/lib/cassanity/version.rb
CHANGED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'cassanity/addition'
|
3
|
+
|
4
|
+
describe Cassanity::Addition do
|
5
|
+
describe "self named helper method" do
|
6
|
+
it "returns instance" do
|
7
|
+
Cassanity::Addition('foo').should eq(described_class.new('foo'))
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#initialize" do
|
12
|
+
context "with value" do
|
13
|
+
before do
|
14
|
+
@instance = described_class.new('foo')
|
15
|
+
end
|
16
|
+
|
17
|
+
it "sets value" do
|
18
|
+
@instance.value.should eq(['foo'])
|
19
|
+
end
|
20
|
+
|
21
|
+
it "sets symbol" do
|
22
|
+
@instance.symbol.should be(:+)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "with multiples values" do
|
27
|
+
before do
|
28
|
+
@instance = described_class.new('foo', 'bar')
|
29
|
+
end
|
30
|
+
|
31
|
+
it "sets values" do
|
32
|
+
@instance.value.should eq(['foo', 'bar'])
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "without value" do
|
37
|
+
it "raises error" do
|
38
|
+
expect {
|
39
|
+
subject.value
|
40
|
+
}.to raise_error(ArgumentError, "value cannot be nil")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "with nil" do
|
45
|
+
it "raises error" do
|
46
|
+
expect {
|
47
|
+
described_class.new(nil)
|
48
|
+
}.to raise_error(ArgumentError, "value cannot be nil")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
shared_examples_for "addition equality" do |method_name|
|
54
|
+
it "returns true for same class and value" do
|
55
|
+
instance = described_class.new('foo')
|
56
|
+
other = described_class.new('foo')
|
57
|
+
instance.send(method_name, other).should be_true
|
58
|
+
end
|
59
|
+
|
60
|
+
it "returns false for same class and different value" do
|
61
|
+
instance = described_class.new('foo')
|
62
|
+
other = described_class.new('bar')
|
63
|
+
instance.send(method_name, other).should be_false
|
64
|
+
end
|
65
|
+
|
66
|
+
it "returns false for different class" do
|
67
|
+
instance = described_class.new('foo')
|
68
|
+
other = Object.new
|
69
|
+
instance.send(method_name, other).should be_false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "#eql?" do
|
74
|
+
include_examples "addition equality", :eql?
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "#==" do
|
78
|
+
include_examples "addition equality", :==
|
79
|
+
end
|
80
|
+
end
|
@@ -80,5 +80,50 @@ describe Cassanity::ArgumentGenerators::Batch do
|
|
80
80
|
}).should eq([cql])
|
81
81
|
end
|
82
82
|
end
|
83
|
+
|
84
|
+
context "with :type key" do
|
85
|
+
it "supports counter batch" do
|
86
|
+
cql = "BEGIN COUNTER BATCH APPLY BATCH"
|
87
|
+
subject.call({
|
88
|
+
type: 'counter',
|
89
|
+
}).should eq([cql])
|
90
|
+
end
|
91
|
+
|
92
|
+
it "supports unlogged batch" do
|
93
|
+
cql = "BEGIN UNLOGGED BATCH APPLY BATCH"
|
94
|
+
subject.call({
|
95
|
+
type: 'unlogged',
|
96
|
+
}).should eq([cql])
|
97
|
+
end
|
98
|
+
|
99
|
+
it "supports default logged batch" do
|
100
|
+
cql = "BEGIN BATCH APPLY BATCH"
|
101
|
+
subject.call({
|
102
|
+
type: 'logged',
|
103
|
+
}).should eq([cql])
|
104
|
+
end
|
105
|
+
|
106
|
+
it "defaults to logged when type is nil" do
|
107
|
+
cql = "BEGIN BATCH APPLY BATCH"
|
108
|
+
subject.call({
|
109
|
+
type: nil,
|
110
|
+
}).should eq([cql])
|
111
|
+
end
|
112
|
+
|
113
|
+
it "defaults to logged when type an empty string" do
|
114
|
+
cql = "BEGIN BATCH APPLY BATCH"
|
115
|
+
subject.call({
|
116
|
+
type: '',
|
117
|
+
}).should eq([cql])
|
118
|
+
end
|
119
|
+
|
120
|
+
it "raises error when type is invalid" do
|
121
|
+
expect {
|
122
|
+
subject.call({
|
123
|
+
type: 'anothertype',
|
124
|
+
})
|
125
|
+
}.to raise_error(ArgumentError, "invalid batch type")
|
126
|
+
end
|
127
|
+
end
|
83
128
|
end
|
84
129
|
end
|
@@ -73,6 +73,26 @@ describe Cassanity::ArgumentGenerators::ColumnFamilyCreate do
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
+
context "when using composite partition key" do
|
77
|
+
it "returns array of arguments" do
|
78
|
+
schema = Cassanity::Schema.new({
|
79
|
+
primary_key: [[:segment, :line], :track_id],
|
80
|
+
columns: {
|
81
|
+
segment: :text,
|
82
|
+
line: :int,
|
83
|
+
track_id: :timeuuid,
|
84
|
+
page: :text,
|
85
|
+
},
|
86
|
+
})
|
87
|
+
cql = "CREATE COLUMNFAMILY #{column_family_name} (segment text, line int, track_id timeuuid, page text, PRIMARY KEY ((segment, line), track_id))"
|
88
|
+
expected = [cql]
|
89
|
+
subject.call({
|
90
|
+
column_family_name: column_family_name,
|
91
|
+
schema: schema,
|
92
|
+
}).should eq(expected)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
76
96
|
context "when using WITH options" do
|
77
97
|
let(:with_clause) {
|
78
98
|
lambda { |args| [" WITH comment = ?", 'Testing']}
|
@@ -58,6 +58,48 @@ describe Cassanity::ArgumentGenerators::ColumnFamilyDelete do
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
+
context "with one collection item" do
|
62
|
+
it "returns array of arguments only deleting the collection item" do
|
63
|
+
cql = "DELETE foo[?] FROM #{column_family_name} WHERE \"id\" = ?"
|
64
|
+
expected = [cql, 0, '1']
|
65
|
+
subject.call({
|
66
|
+
column_family_name: column_family_name,
|
67
|
+
columns: Cassanity.item(0, :foo),
|
68
|
+
where: {
|
69
|
+
id: '1',
|
70
|
+
}
|
71
|
+
}).should eq(expected)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context "with multiple collection items" do
|
76
|
+
it "returns array of arguments only deleting the collection items" do
|
77
|
+
cql = "DELETE foo[?], foo[?] FROM #{column_family_name} WHERE \"id\" = ?"
|
78
|
+
expected = [cql, 0, 3, '1']
|
79
|
+
subject.call({
|
80
|
+
column_family_name: column_family_name,
|
81
|
+
columns: [Cassanity.item(0, :foo), Cassanity.item(3, :foo)],
|
82
|
+
where: {
|
83
|
+
id: '1',
|
84
|
+
}
|
85
|
+
}).should eq(expected)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context "with standard columns and collection items" do
|
90
|
+
it "returns array of arguments only deleting given columns" do
|
91
|
+
cql = "DELETE bar, foo[?] FROM #{column_family_name} WHERE \"id\" = ?"
|
92
|
+
expected = [cql, 0, '1']
|
93
|
+
subject.call({
|
94
|
+
column_family_name: column_family_name,
|
95
|
+
columns: [:bar, Cassanity.item(0, :foo)],
|
96
|
+
where: {
|
97
|
+
id: '1',
|
98
|
+
}
|
99
|
+
}).should eq(expected)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
61
103
|
context "with :where key" do
|
62
104
|
subject {
|
63
105
|
described_class.new({
|
@@ -24,6 +24,17 @@ describe Cassanity::ArgumentGenerators::KeyspaceCreate do
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
context "overriding replication class with NetworkTopologyStrategy" do
|
28
|
+
it "doesn't merge in replication_factor" do
|
29
|
+
cql = "CREATE KEYSPACE #{keyspace_name} WITH replication = ?"
|
30
|
+
expected = [cql, {class: 'NetworkTopologyStrategy', datacenter1: 1}]
|
31
|
+
subject.call({
|
32
|
+
keyspace_name: keyspace_name,
|
33
|
+
replication: {class: 'NetworkTopologyStrategy', datacenter1: 1},
|
34
|
+
}).should eq(expected)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
27
38
|
context "overriding a default strategy_option" do
|
28
39
|
it "returns array of arguments" do
|
29
40
|
cql = "CREATE KEYSPACE #{keyspace_name} WITH replication = ?"
|
@@ -44,5 +44,40 @@ describe Cassanity::ArgumentGenerators::SetClause do
|
|
44
44
|
should eq([" SET views = views - ?", 3])
|
45
45
|
end
|
46
46
|
end
|
47
|
+
|
48
|
+
context "with addition" do
|
49
|
+
it "returns array of arguments with SET including list value" do
|
50
|
+
subject.call(set: {places: Cassanity::Addition.new('mordor')}).
|
51
|
+
should eq([" SET places = places + ?", ['mordor']])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "with removal" do
|
56
|
+
it "returns array of arguments with SET including list value" do
|
57
|
+
subject.call(set: {places: Cassanity::Removal.new('mordor')}).
|
58
|
+
should eq([" SET places = places - ?", ['mordor']])
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "with set_addition" do
|
63
|
+
it "returns array of arguments with SET including set value" do
|
64
|
+
subject.call(set: {places: Cassanity::SetAddition.new('mordor')}).
|
65
|
+
should eq([" SET places = places + ?", Set['mordor']])
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "with set_removal" do
|
70
|
+
it "returns array of arguments with SET including set value" do
|
71
|
+
subject.call(set: {places: Cassanity::SetRemoval.new('mordor')}).
|
72
|
+
should eq([" SET places = places - ?", Set['mordor']])
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context "with collection_item" do
|
77
|
+
it "returns array of arguments with SET including collection item" do
|
78
|
+
subject.call(set: {tags: Cassanity::CollectionItem.new(3,'ruby')}).
|
79
|
+
should eq([" SET tags[?] = ?", 3, 'ruby'])
|
80
|
+
end
|
81
|
+
end
|
47
82
|
end
|
48
83
|
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'cassanity/collection_item'
|
3
|
+
|
4
|
+
describe Cassanity::CollectionItem do
|
5
|
+
subject {
|
6
|
+
described_class.new(1, 'ruby')
|
7
|
+
}
|
8
|
+
|
9
|
+
describe "self named helper method" do
|
10
|
+
it "returns instance" do
|
11
|
+
Cassanity::CollectionItem(0, 'ruby').should eq(described_class.new(0, 'ruby'))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#initialize" do
|
16
|
+
before do
|
17
|
+
@instance = described_class.new(1, 'ruby')
|
18
|
+
end
|
19
|
+
|
20
|
+
it "sets key" do
|
21
|
+
@instance.key.should eq(1)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "sets value" do
|
25
|
+
@instance.value.should eq('ruby')
|
26
|
+
end
|
27
|
+
|
28
|
+
context "with key nil" do
|
29
|
+
it "raises error" do
|
30
|
+
expect {
|
31
|
+
described_class.new(nil, 3)
|
32
|
+
}.to raise_error(ArgumentError, "key cannot be nil")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "with value nil" do
|
37
|
+
it "raises error" do
|
38
|
+
expect {
|
39
|
+
described_class.new(3, nil)
|
40
|
+
}.to raise_error(ArgumentError, "value cannot be nil")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
shared_examples_for "operator equality" do |method_name|
|
46
|
+
it "returns true for same class, key and value" do
|
47
|
+
instance = described_class.new(0, 'ruby')
|
48
|
+
other = described_class.new(0, 'ruby')
|
49
|
+
instance.send(method_name, other).should be_true
|
50
|
+
end
|
51
|
+
|
52
|
+
it "returns false for same class/value and different key" do
|
53
|
+
instance = described_class.new(0, 'ruby')
|
54
|
+
other = described_class.new(1, 'ruby')
|
55
|
+
instance.send(method_name, other).should be_false
|
56
|
+
end
|
57
|
+
|
58
|
+
it "returns false for same class/key and different value" do
|
59
|
+
instance = described_class.new(0, 'ruby')
|
60
|
+
other = described_class.new(0, 'go')
|
61
|
+
instance.send(method_name, other).should be_false
|
62
|
+
end
|
63
|
+
|
64
|
+
it "returns false for different class" do
|
65
|
+
instance = described_class.new(1, 'ruby')
|
66
|
+
other = Object.new
|
67
|
+
instance.send(method_name, other).should be_false
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "#eql?" do
|
72
|
+
include_examples "operator equality", :eql?
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "#==" do
|
76
|
+
include_examples "operator equality", :==
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "#inspect" do
|
80
|
+
it "return representation" do
|
81
|
+
subject.inspect.should eq("#<Cassanity::CollectionItem:#{subject.object_id} key=1, value=\"ruby\">")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'cassanity/removal'
|
3
|
+
|
4
|
+
describe Cassanity::Removal do
|
5
|
+
describe "self named helper method" do
|
6
|
+
it "returns instance" do
|
7
|
+
Cassanity::Removal('foo').should eq(described_class.new('foo'))
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#initialize" do
|
12
|
+
context "with value" do
|
13
|
+
before do
|
14
|
+
@instance = described_class.new('foo')
|
15
|
+
end
|
16
|
+
|
17
|
+
it "sets value" do
|
18
|
+
@instance.value.should eq(['foo'])
|
19
|
+
end
|
20
|
+
|
21
|
+
it "sets symbol" do
|
22
|
+
@instance.symbol.should be(:-)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "with multiples values" do
|
27
|
+
before do
|
28
|
+
@instance = described_class.new('foo', 'bar')
|
29
|
+
end
|
30
|
+
|
31
|
+
it "sets values" do
|
32
|
+
@instance.value.should eq(['foo', 'bar'])
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "without value" do
|
37
|
+
it "raises error" do
|
38
|
+
expect {
|
39
|
+
subject.value
|
40
|
+
}.to raise_error(ArgumentError, "value cannot be nil")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "with nil" do
|
45
|
+
it "raises error" do
|
46
|
+
expect {
|
47
|
+
described_class.new(nil)
|
48
|
+
}.to raise_error(ArgumentError, "value cannot be nil")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
shared_examples_for "removal equality" do |method_name|
|
54
|
+
it "returns true for same class and value" do
|
55
|
+
instance = described_class.new('foo')
|
56
|
+
other = described_class.new('foo')
|
57
|
+
instance.send(method_name, other).should be_true
|
58
|
+
end
|
59
|
+
|
60
|
+
it "returns false for same class and different value" do
|
61
|
+
instance = described_class.new('foo')
|
62
|
+
other = described_class.new('bar')
|
63
|
+
instance.send(method_name, other).should be_false
|
64
|
+
end
|
65
|
+
|
66
|
+
it "returns false for different class" do
|
67
|
+
instance = described_class.new('foo')
|
68
|
+
other = Object.new
|
69
|
+
instance.send(method_name, other).should be_false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "#eql?" do
|
74
|
+
include_examples "removal equality", :eql?
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "#==" do
|
78
|
+
include_examples "removal equality", :==
|
79
|
+
end
|
80
|
+
end
|