cassanity 0.2.2 → 0.3.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.
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'