cassanity 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Changelog.md +5 -0
- data/Guardfile +8 -1
- data/README.md +8 -0
- data/examples/_shared.rb +1 -0
- data/examples/batch.rb +4 -1
- data/examples/column_families.rb +3 -1
- data/examples/counters.rb +90 -0
- data/examples/keyspaces.rb +3 -1
- data/examples/select_range.rb +118 -0
- data/lib/cassanity/argument_generators/set_clause.rb +7 -8
- data/lib/cassanity/argument_generators/where_clause.rb +19 -1
- data/lib/cassanity/decrement.rb +27 -0
- data/lib/cassanity/executors/cassandra_cql.rb +1 -1
- data/lib/cassanity/increment.rb +27 -0
- data/lib/cassanity/operator.rb +27 -0
- data/lib/cassanity/operators/eq.rb +15 -0
- data/lib/cassanity/operators/gt.rb +15 -0
- data/lib/cassanity/operators/gte.rb +15 -0
- data/lib/cassanity/operators/lt.rb +15 -0
- data/lib/cassanity/operators/lte.rb +15 -0
- data/lib/cassanity/version.rb +1 -1
- data/lib/cassanity.rb +84 -0
- data/spec/integration/cassanity/column_family_spec.rb +69 -2
- data/spec/unit/cassanity/argument_generators/set_clause_spec.rb +9 -46
- data/spec/unit/cassanity/argument_generators/where_clause_spec.rb +87 -8
- data/spec/unit/cassanity/decrement_spec.rb +68 -0
- data/spec/unit/cassanity/increment_spec.rb +68 -0
- data/spec/unit/cassanity/operator_spec.rb +58 -0
- data/spec/unit/cassanity/operators/eq_spec.rb +24 -0
- data/spec/unit/cassanity/operators/gt_spec.rb +24 -0
- data/spec/unit/cassanity/operators/gte_spec.rb +24 -0
- data/spec/unit/cassanity/operators/lt_spec.rb +24 -0
- data/spec/unit/cassanity/operators/lte_spec.rb +24 -0
- data/spec/unit/cassanity_spec.rb +118 -0
- metadata +30 -4
data/Changelog.md
CHANGED
@@ -2,6 +2,11 @@
|
|
2
2
|
|
3
3
|
Not all changes will be here, but the important ones will be for sure.
|
4
4
|
|
5
|
+
## 0.3.0
|
6
|
+
|
7
|
+
* Changed [update counter value API](https://github.com/jnunemaker/cassanity/commit/a0f5a76)
|
8
|
+
* Added [support for range queries](https://github.com/jnunemaker/cassanity/commit/5d89ada)
|
9
|
+
|
5
10
|
## 0.2.2
|
6
11
|
|
7
12
|
* Added [Keyspace#column_families](https://github.com/jnunemaker/cassanity/commit/8101835)
|
data/Guardfile
CHANGED
@@ -6,7 +6,14 @@ guard 'bundler' do
|
|
6
6
|
watch(/^.+\.gemspec/)
|
7
7
|
end
|
8
8
|
|
9
|
-
|
9
|
+
rspec_options = {
|
10
|
+
version: 2,
|
11
|
+
all_after_pass: false,
|
12
|
+
all_on_start: false,
|
13
|
+
keep_failed: false
|
14
|
+
}
|
15
|
+
|
16
|
+
guard 'rspec', rspec_options do
|
10
17
|
watch(%r{^spec/.+_spec\.rb$})
|
11
18
|
watch(%r{^lib/(.+)\.rb$}) { |m| [
|
12
19
|
"spec/unit/#{m[1]}_spec.rb",
|
data/README.md
CHANGED
@@ -84,6 +84,14 @@ apps.truncate
|
|
84
84
|
apps.drop
|
85
85
|
```
|
86
86
|
|
87
|
+
You can also do a lot more. Here are a few more [examples](https://github.com/jnunemaker/cassanity/tree/master/examples):
|
88
|
+
|
89
|
+
* [Batch Operations](https://github.com/jnunemaker/cassanity/tree/master/examples/batch.rb)
|
90
|
+
* [Counters](https://github.com/jnunemaker/cassanity/tree/master/examples/counters.rb)
|
91
|
+
* [Keyspaces](https://github.com/jnunemaker/cassanity/tree/master/examples/keyspaces.rb)
|
92
|
+
* [Column Families](https://github.com/jnunemaker/cassanity/tree/master/examples/column_families.rb)
|
93
|
+
* [Select a Range](https://github.com/jnunemaker/cassanity/tree/master/examples/select_range.rb)
|
94
|
+
|
87
95
|
## Compatibility
|
88
96
|
|
89
97
|
* Ruby 1.9.3
|
data/examples/_shared.rb
CHANGED
data/examples/batch.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
require_relative '_shared'
|
2
2
|
require 'cassanity'
|
3
3
|
|
4
|
-
client = CassandraCQL::Database.new('127.0.0.1:9160'
|
4
|
+
client = CassandraCQL::Database.new('127.0.0.1:9160', {
|
5
|
+
cql_version: '3.0.0',
|
6
|
+
})
|
7
|
+
|
5
8
|
executor = Cassanity::Executors::CassandraCql.new(client: client)
|
6
9
|
|
7
10
|
connection = Cassanity::Connection.new(executor: executor)
|
data/examples/column_families.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
require_relative '_shared'
|
2
2
|
require 'cassanity'
|
3
3
|
|
4
|
-
client = CassandraCQL::Database.new('127.0.0.1:9160'
|
4
|
+
client = CassandraCQL::Database.new('127.0.0.1:9160', {
|
5
|
+
cql_version: '3.0.0',
|
6
|
+
})
|
5
7
|
executor = Cassanity::Executors::CassandraCql.new(client: client)
|
6
8
|
|
7
9
|
connection = Cassanity::Connection.new(executor: executor)
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require_relative '_shared'
|
2
|
+
require 'cassanity'
|
3
|
+
|
4
|
+
client = CassandraCQL::Database.new('127.0.0.1:9160', {
|
5
|
+
cql_version: '3.0.0',
|
6
|
+
})
|
7
|
+
|
8
|
+
executor = Cassanity::Executors::CassandraCql.new({
|
9
|
+
client: client,
|
10
|
+
logger: Logger.new(STDOUT),
|
11
|
+
})
|
12
|
+
|
13
|
+
connection = Cassanity::Connection.new(executor: executor)
|
14
|
+
keyspace = connection['cassanity_examples']
|
15
|
+
keyspace.recreate
|
16
|
+
|
17
|
+
rollups_schema = Cassanity::Schema.new({
|
18
|
+
primary_key: :id,
|
19
|
+
columns: {
|
20
|
+
id: :text,
|
21
|
+
value: :counter,
|
22
|
+
},
|
23
|
+
})
|
24
|
+
|
25
|
+
# get an instance of a column family, providing schema means it can create itself
|
26
|
+
rollups = keyspace.column_family({
|
27
|
+
name: :rollups,
|
28
|
+
schema: rollups_schema,
|
29
|
+
})
|
30
|
+
|
31
|
+
# create column family based on schema
|
32
|
+
rollups.create
|
33
|
+
|
34
|
+
# increment by 1
|
35
|
+
rollups.update({
|
36
|
+
set: {value: Cassanity::Increment.new},
|
37
|
+
where: {id: :views},
|
38
|
+
})
|
39
|
+
|
40
|
+
# increment by 3
|
41
|
+
rollups.update({
|
42
|
+
set: {value: Cassanity::Increment.new(3)},
|
43
|
+
where: {id: :views},
|
44
|
+
})
|
45
|
+
|
46
|
+
# increment by 3
|
47
|
+
rollups.update({
|
48
|
+
set: {value: Cassanity::Increment(3)},
|
49
|
+
where: {id: :views},
|
50
|
+
})
|
51
|
+
|
52
|
+
# increment by 3
|
53
|
+
# you can also use .incr and .increment
|
54
|
+
rollups.update({
|
55
|
+
set: {value: Cassanity.inc(3)},
|
56
|
+
where: {id: :views},
|
57
|
+
})
|
58
|
+
|
59
|
+
# returns 10
|
60
|
+
pp rollups.select(where: {id: :views})[0]['value']
|
61
|
+
|
62
|
+
# decrement by 1
|
63
|
+
rollups.update({
|
64
|
+
set: {value: Cassanity::Decrement.new},
|
65
|
+
where: {id: :views},
|
66
|
+
})
|
67
|
+
|
68
|
+
# decrement by 2
|
69
|
+
rollups.update({
|
70
|
+
set: {value: Cassanity::Decrement.new(2)},
|
71
|
+
where: {id: :views},
|
72
|
+
})
|
73
|
+
|
74
|
+
# decrement by 2
|
75
|
+
rollups.update({
|
76
|
+
set: {value: Cassanity::Decrement(2)},
|
77
|
+
where: {id: :views},
|
78
|
+
})
|
79
|
+
|
80
|
+
# decrement by 2
|
81
|
+
# you can also use .decr and .decrement
|
82
|
+
rollups.update({
|
83
|
+
set: {value: Cassanity.dec(2)},
|
84
|
+
where: {id: :views},
|
85
|
+
})
|
86
|
+
|
87
|
+
# returns 3
|
88
|
+
pp rollups.select(where: {id: :views})[0]['value']
|
89
|
+
|
90
|
+
keyspace.drop
|
data/examples/keyspaces.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
require_relative '_shared'
|
2
2
|
require 'cassanity'
|
3
3
|
|
4
|
-
client = CassandraCQL::Database.new('127.0.0.1:9160'
|
4
|
+
client = CassandraCQL::Database.new('127.0.0.1:9160', {
|
5
|
+
cql_version: '3.0.0',
|
6
|
+
})
|
5
7
|
executor = Cassanity::Executors::CassandraCql.new(client: client)
|
6
8
|
|
7
9
|
connection = Cassanity::Connection.new(executor: executor)
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require_relative '_shared'
|
2
|
+
require 'cassanity'
|
3
|
+
|
4
|
+
client = CassandraCQL::Database.new('127.0.0.1:9160', {
|
5
|
+
cql_version: '3.0.0',
|
6
|
+
})
|
7
|
+
|
8
|
+
executor = Cassanity::Executors::CassandraCql.new({
|
9
|
+
client: client,
|
10
|
+
logger: Logger.new(STDOUT),
|
11
|
+
})
|
12
|
+
|
13
|
+
connection = Cassanity::Connection.new(executor: executor)
|
14
|
+
keyspace = connection['cassanity_examples']
|
15
|
+
keyspace.recreate
|
16
|
+
|
17
|
+
rollups_schema = Cassanity::Schema.new({
|
18
|
+
primary_key: [:id, :timestamp],
|
19
|
+
columns: {
|
20
|
+
id: :text,
|
21
|
+
timestamp: :int,
|
22
|
+
value: :counter,
|
23
|
+
},
|
24
|
+
})
|
25
|
+
|
26
|
+
# get an instance of a column family, providing schema means it can create itself
|
27
|
+
rollups = keyspace.column_family({
|
28
|
+
name: :rollups,
|
29
|
+
schema: rollups_schema,
|
30
|
+
})
|
31
|
+
|
32
|
+
# create column family based on schema
|
33
|
+
rollups.create
|
34
|
+
|
35
|
+
[
|
36
|
+
[1, rand(1_000)],
|
37
|
+
[2, rand(1_000)],
|
38
|
+
[3, rand(1_000)],
|
39
|
+
[4, rand(1_000)],
|
40
|
+
[5, rand(1_000)],
|
41
|
+
].each do |pair|
|
42
|
+
timestamp, value = pair
|
43
|
+
rollups.update({
|
44
|
+
set: {value: Cassanity::Increment.new(value)},
|
45
|
+
where: {
|
46
|
+
id: :views,
|
47
|
+
timestamp: timestamp,
|
48
|
+
}
|
49
|
+
})
|
50
|
+
end
|
51
|
+
|
52
|
+
# returns timestamps 1, 2 and 3
|
53
|
+
pp rollups.select({
|
54
|
+
where: {
|
55
|
+
id: :views,
|
56
|
+
timestamp: Range.new(1, 3),
|
57
|
+
}
|
58
|
+
})
|
59
|
+
|
60
|
+
# also works with exclusion of end ranges
|
61
|
+
# returns 1 and 2
|
62
|
+
pp rollups.select({
|
63
|
+
where: {
|
64
|
+
id: :views,
|
65
|
+
timestamp: Range.new(1, 3, true),
|
66
|
+
}
|
67
|
+
})
|
68
|
+
|
69
|
+
# also works with operators
|
70
|
+
# returns 3, 4 and 5
|
71
|
+
pp rollups.select({
|
72
|
+
where: {
|
73
|
+
id: :views,
|
74
|
+
timestamp: Cassanity::Operator.new(:>, 2),
|
75
|
+
}
|
76
|
+
})
|
77
|
+
|
78
|
+
# returns 2, 3, 4 and 5
|
79
|
+
pp rollups.select({
|
80
|
+
where: {
|
81
|
+
id: :views,
|
82
|
+
timestamp: Cassanity::Operator.new(:>=, 2),
|
83
|
+
}
|
84
|
+
})
|
85
|
+
|
86
|
+
puts "\n\n ALL BELOW SHOULD RETURN 1 \n\n"
|
87
|
+
|
88
|
+
# returns 1
|
89
|
+
pp rollups.select({
|
90
|
+
where: {
|
91
|
+
id: :views,
|
92
|
+
timestamp: Cassanity::Operator.new(:<, 2),
|
93
|
+
}
|
94
|
+
})
|
95
|
+
|
96
|
+
# returns 1
|
97
|
+
pp rollups.select({
|
98
|
+
where: {
|
99
|
+
id: :views,
|
100
|
+
timestamp: Cassanity::Operators::Lt.new(2),
|
101
|
+
}
|
102
|
+
})
|
103
|
+
|
104
|
+
# returns 1
|
105
|
+
pp rollups.select({
|
106
|
+
where: {
|
107
|
+
id: :views,
|
108
|
+
timestamp: Cassanity::Operators::Lt(2),
|
109
|
+
}
|
110
|
+
})
|
111
|
+
|
112
|
+
# returns 1
|
113
|
+
pp rollups.select({
|
114
|
+
where: {
|
115
|
+
id: :views,
|
116
|
+
timestamp: Cassanity.lt(2),
|
117
|
+
}
|
118
|
+
})
|
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'cassanity/increment'
|
2
|
+
require 'cassanity/decrement'
|
3
|
+
|
1
4
|
module Cassanity
|
2
5
|
module ArgumentGenerators
|
3
6
|
class SetClause
|
@@ -8,8 +11,10 @@ module Cassanity
|
|
8
11
|
cql, variables, sets = '', [], []
|
9
12
|
|
10
13
|
set.each do |key, value|
|
11
|
-
|
12
|
-
|
14
|
+
case value
|
15
|
+
when Cassanity::Increment, Cassanity::Decrement
|
16
|
+
sets << "#{key} = #{key} #{value.symbol} ?"
|
17
|
+
variables << value.value
|
13
18
|
else
|
14
19
|
sets << "#{key} = ?"
|
15
20
|
variables << value
|
@@ -17,14 +22,8 @@ module Cassanity
|
|
17
22
|
end
|
18
23
|
cql << " SET #{sets.join(', ')}"
|
19
24
|
|
20
|
-
|
21
25
|
[cql, *variables]
|
22
26
|
end
|
23
|
-
|
24
|
-
# Private
|
25
|
-
def counter?(key, value)
|
26
|
-
value.is_a?(String) && value.match(/#{key}(\s+)?[\+\-](\s+)?\d/)
|
27
|
-
end
|
28
27
|
end
|
29
28
|
end
|
30
29
|
end
|
@@ -1,3 +1,10 @@
|
|
1
|
+
require 'cassanity/operator'
|
2
|
+
require 'cassanity/operators/eq'
|
3
|
+
require 'cassanity/operators/gt'
|
4
|
+
require 'cassanity/operators/gte'
|
5
|
+
require 'cassanity/operators/lt'
|
6
|
+
require 'cassanity/operators/lte'
|
7
|
+
|
1
8
|
module Cassanity
|
2
9
|
module ArgumentGenerators
|
3
10
|
class WhereClause
|
@@ -11,9 +18,20 @@ module Cassanity
|
|
11
18
|
variables, wheres = [], []
|
12
19
|
|
13
20
|
where.each do |key, value|
|
14
|
-
|
21
|
+
case value
|
22
|
+
when Array
|
15
23
|
wheres << "#{key} IN (?)"
|
16
24
|
variables << value
|
25
|
+
when Range
|
26
|
+
start, finish = value.begin, value.end
|
27
|
+
end_operator = value.exclude_end? ? '<' : '<='
|
28
|
+
wheres << "#{key} >= ?"
|
29
|
+
wheres << "#{key} #{end_operator} ?"
|
30
|
+
variables << start
|
31
|
+
variables << finish
|
32
|
+
when Cassanity::Operator
|
33
|
+
wheres << "#{key} #{value.symbol} ?"
|
34
|
+
variables << value.value
|
17
35
|
else
|
18
36
|
wheres << "#{key} = ?"
|
19
37
|
variables << value
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Cassanity
|
2
|
+
def self.Decrement(*args)
|
3
|
+
Decrement.new(*args)
|
4
|
+
end
|
5
|
+
|
6
|
+
class Decrement
|
7
|
+
# Internal
|
8
|
+
attr_reader :symbol
|
9
|
+
|
10
|
+
# Internal
|
11
|
+
attr_reader :value
|
12
|
+
|
13
|
+
# Public: Returns an decrement instance
|
14
|
+
def initialize(value = 1)
|
15
|
+
raise ArgumentError.new("value cannot be nil") if value.nil?
|
16
|
+
|
17
|
+
@symbol = :-
|
18
|
+
@value = value
|
19
|
+
end
|
20
|
+
|
21
|
+
def eql?(other)
|
22
|
+
self.class.eql?(other.class) && value == other.value
|
23
|
+
end
|
24
|
+
|
25
|
+
alias_method :==, :eql?
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Cassanity
|
2
|
+
def self.Increment(*args)
|
3
|
+
Increment.new(*args)
|
4
|
+
end
|
5
|
+
|
6
|
+
class Increment
|
7
|
+
# Internal
|
8
|
+
attr_reader :symbol
|
9
|
+
|
10
|
+
# Internal
|
11
|
+
attr_reader :value
|
12
|
+
|
13
|
+
# Public: Returns an increment instance
|
14
|
+
def initialize(value = 1)
|
15
|
+
raise ArgumentError.new("value cannot be nil") if value.nil?
|
16
|
+
|
17
|
+
@symbol = :+
|
18
|
+
@value = value
|
19
|
+
end
|
20
|
+
|
21
|
+
def eql?(other)
|
22
|
+
self.class.eql?(other.class) && value == other.value
|
23
|
+
end
|
24
|
+
|
25
|
+
alias_method :==, :eql?
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Cassanity
|
2
|
+
def self.Operator(*args)
|
3
|
+
Operator.new(*args)
|
4
|
+
end
|
5
|
+
|
6
|
+
class Operator
|
7
|
+
# Internal
|
8
|
+
attr_reader :symbol
|
9
|
+
|
10
|
+
# Internal
|
11
|
+
attr_reader :value
|
12
|
+
|
13
|
+
# Public: Returns an operator instance
|
14
|
+
def initialize(symbol, value)
|
15
|
+
@symbol = symbol
|
16
|
+
@value = value
|
17
|
+
end
|
18
|
+
|
19
|
+
def eql?(other)
|
20
|
+
self.class.eql?(other.class) &&
|
21
|
+
value == other.value &&
|
22
|
+
symbol == other.symbol
|
23
|
+
end
|
24
|
+
|
25
|
+
alias_method :==, :eql?
|
26
|
+
end
|
27
|
+
end
|
data/lib/cassanity/version.rb
CHANGED
data/lib/cassanity.rb
CHANGED
@@ -1,4 +1,88 @@
|
|
1
|
+
require 'cassanity/operators/eq'
|
2
|
+
require 'cassanity/operators/gt'
|
3
|
+
require 'cassanity/operators/gte'
|
4
|
+
require 'cassanity/operators/lt'
|
5
|
+
require 'cassanity/operators/lte'
|
6
|
+
|
1
7
|
module Cassanity
|
8
|
+
# Public: Shortcut for returning an equality operator.
|
9
|
+
#
|
10
|
+
# args - The arguments to pass to the initialize method of the operator.
|
11
|
+
#
|
12
|
+
# Returns a Cassanity::Operators::Eq instance.
|
13
|
+
def self.eq(*args)
|
14
|
+
Operators::Eq.new(*args)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Public: Shortcut for returning a less than operator.
|
18
|
+
#
|
19
|
+
# args - The arguments to pass to the initialize method of the operator.
|
20
|
+
#
|
21
|
+
# Returns a Cassanity::Operators::Lt instance.
|
22
|
+
def self.lt(*args)
|
23
|
+
Operators::Lt.new(*args)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Public: Shortcut for returning a less than or equal to operator.
|
27
|
+
#
|
28
|
+
# args - The arguments to pass to the initialize method of the operator.
|
29
|
+
#
|
30
|
+
# Returns a Cassanity::Operators::Lte instance.
|
31
|
+
def self.lte(*args)
|
32
|
+
Operators::Lte.new(*args)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Public: Shortcut for returning a greater than operator.
|
36
|
+
#
|
37
|
+
# args - The arguments to pass to the initialize method of the operator.
|
38
|
+
#
|
39
|
+
# Returns a Cassanity::Operators::Gt instance.
|
40
|
+
def self.gt(*args)
|
41
|
+
Operators::Gt.new(*args)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Public: Shortcut for returning a greater than or equal to operator.
|
45
|
+
#
|
46
|
+
# args - The arguments to pass to the initialize method of the operator.
|
47
|
+
#
|
48
|
+
# Returns a Cassanity::Operators::Gte instance.
|
49
|
+
def self.gte(*args)
|
50
|
+
Operators::Gte.new(*args)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Public: Shortcut for returning an increment value for a counter update.
|
54
|
+
#
|
55
|
+
# value - The value to initialize the increment with (optional, default: 1).
|
56
|
+
#
|
57
|
+
# Returns a Cassanity::Increment instance.
|
58
|
+
def self.inc(value = 1)
|
59
|
+
Increment.new(value)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Public: Shortcut for returning a decrement value for a counter update.
|
63
|
+
#
|
64
|
+
# value - The value to initialize the decrement with (optional, default: 1).
|
65
|
+
#
|
66
|
+
# Returns a Cassanity::Decrement instance.
|
67
|
+
def self.dec(value = 1)
|
68
|
+
Decrement.new(value)
|
69
|
+
end
|
70
|
+
|
71
|
+
class << self
|
72
|
+
alias_method :equal, :eq
|
73
|
+
|
74
|
+
alias_method :greater_than, :gt
|
75
|
+
alias_method :greater_than_or_equal_to, :gte
|
76
|
+
|
77
|
+
alias_method :less_than, :lt
|
78
|
+
alias_method :less_than_or_equal_to, :lte
|
79
|
+
|
80
|
+
alias_method :incr, :inc
|
81
|
+
alias_method :increment, :inc
|
82
|
+
|
83
|
+
alias_method :decr, :dec
|
84
|
+
alias_method :decrement, :dec
|
85
|
+
end
|
2
86
|
end
|
3
87
|
|
4
88
|
require 'cassanity/connection'
|