cassanity 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. data/Changelog.md +5 -0
  2. data/Guardfile +8 -1
  3. data/README.md +8 -0
  4. data/examples/_shared.rb +1 -0
  5. data/examples/batch.rb +4 -1
  6. data/examples/column_families.rb +3 -1
  7. data/examples/counters.rb +90 -0
  8. data/examples/keyspaces.rb +3 -1
  9. data/examples/select_range.rb +118 -0
  10. data/lib/cassanity/argument_generators/set_clause.rb +7 -8
  11. data/lib/cassanity/argument_generators/where_clause.rb +19 -1
  12. data/lib/cassanity/decrement.rb +27 -0
  13. data/lib/cassanity/executors/cassandra_cql.rb +1 -1
  14. data/lib/cassanity/increment.rb +27 -0
  15. data/lib/cassanity/operator.rb +27 -0
  16. data/lib/cassanity/operators/eq.rb +15 -0
  17. data/lib/cassanity/operators/gt.rb +15 -0
  18. data/lib/cassanity/operators/gte.rb +15 -0
  19. data/lib/cassanity/operators/lt.rb +15 -0
  20. data/lib/cassanity/operators/lte.rb +15 -0
  21. data/lib/cassanity/version.rb +1 -1
  22. data/lib/cassanity.rb +84 -0
  23. data/spec/integration/cassanity/column_family_spec.rb +69 -2
  24. data/spec/unit/cassanity/argument_generators/set_clause_spec.rb +9 -46
  25. data/spec/unit/cassanity/argument_generators/where_clause_spec.rb +87 -8
  26. data/spec/unit/cassanity/decrement_spec.rb +68 -0
  27. data/spec/unit/cassanity/increment_spec.rb +68 -0
  28. data/spec/unit/cassanity/operator_spec.rb +58 -0
  29. data/spec/unit/cassanity/operators/eq_spec.rb +24 -0
  30. data/spec/unit/cassanity/operators/gt_spec.rb +24 -0
  31. data/spec/unit/cassanity/operators/gte_spec.rb +24 -0
  32. data/spec/unit/cassanity/operators/lt_spec.rb +24 -0
  33. data/spec/unit/cassanity/operators/lte_spec.rb +24 -0
  34. data/spec/unit/cassanity_spec.rb +118 -0
  35. 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
- guard 'rspec', :version => 2 do
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
@@ -2,6 +2,7 @@
2
2
  # Sets up load path for examples and requires some stuff
3
3
  require 'pp'
4
4
  require 'pathname'
5
+ require 'logger'
5
6
 
6
7
  root_path = Pathname(__FILE__).dirname.join('..').expand_path
7
8
  lib_path = root_path.join('lib')
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)
@@ -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
@@ -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
- if counter?(key, value)
12
- sets << "#{key} = #{value}"
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
- if value.is_a?(Array)
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
@@ -78,7 +78,7 @@ module Cassanity
78
78
  #
79
79
  # Examples
80
80
  #
81
- # client = CassandraCQL::Database.new('host')
81
+ # client = CassandraCQL::Database.new('host', cql_version: '3.0.0')
82
82
  # Cassanity::Executors::CassandraCql.new(client: client)
83
83
  #
84
84
  def initialize(args = {})
@@ -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
@@ -0,0 +1,15 @@
1
+ require 'cassanity/operator'
2
+
3
+ module Cassanity
4
+ module Operators
5
+ def self.Eq(*args)
6
+ Eq.new(*args)
7
+ end
8
+
9
+ class Eq < Operator
10
+ def initialize(value)
11
+ super :"=", value
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ require 'cassanity/operator'
2
+
3
+ module Cassanity
4
+ module Operators
5
+ def self.Gt(*args)
6
+ Gt.new(*args)
7
+ end
8
+
9
+ class Gt < Operator
10
+ def initialize(value)
11
+ super(:>, value)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ require 'cassanity/operator'
2
+
3
+ module Cassanity
4
+ module Operators
5
+ def self.Gte(*args)
6
+ Gte.new(*args)
7
+ end
8
+
9
+ class Gte < Operator
10
+ def initialize(value)
11
+ super(:>=, value)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ require 'cassanity/operator'
2
+
3
+ module Cassanity
4
+ module Operators
5
+ def self.Lt(*args)
6
+ Lt.new(*args)
7
+ end
8
+
9
+ class Lt < Operator
10
+ def initialize(value)
11
+ super(:<, value)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ require 'cassanity/operator'
2
+
3
+ module Cassanity
4
+ module Operators
5
+ def self.Lte(*args)
6
+ Lte.new(*args)
7
+ end
8
+
9
+ class Lte < Operator
10
+ def initialize(value)
11
+ super(:<=, value)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,3 +1,3 @@
1
1
  module Cassanity
2
- VERSION = "0.2.2"
2
+ VERSION = "0.3.0"
3
3
  end
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'