cassanity 0.1.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 (76) hide show
  1. data/.gitignore +19 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +10 -0
  4. data/Gemfile +11 -0
  5. data/Guardfile +17 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +99 -0
  8. data/Rakefile +16 -0
  9. data/cassanity.gemspec +21 -0
  10. data/examples/_shared.rb +8 -0
  11. data/examples/batch.rb +40 -0
  12. data/examples/column_families.rb +68 -0
  13. data/examples/keyspaces.rb +57 -0
  14. data/lib/cassanity/argument_generators/batch.rb +52 -0
  15. data/lib/cassanity/argument_generators/column_family_alter.rb +47 -0
  16. data/lib/cassanity/argument_generators/column_family_create.rb +44 -0
  17. data/lib/cassanity/argument_generators/column_family_delete.rb +65 -0
  18. data/lib/cassanity/argument_generators/column_family_drop.rb +18 -0
  19. data/lib/cassanity/argument_generators/column_family_insert.rb +53 -0
  20. data/lib/cassanity/argument_generators/column_family_select.rb +34 -0
  21. data/lib/cassanity/argument_generators/column_family_truncate.rb +18 -0
  22. data/lib/cassanity/argument_generators/column_family_update.rb +69 -0
  23. data/lib/cassanity/argument_generators/index_create.rb +22 -0
  24. data/lib/cassanity/argument_generators/index_drop.rb +13 -0
  25. data/lib/cassanity/argument_generators/keyspace_create.rb +51 -0
  26. data/lib/cassanity/argument_generators/keyspace_drop.rb +13 -0
  27. data/lib/cassanity/argument_generators/keyspace_use.rb +13 -0
  28. data/lib/cassanity/argument_generators/keyspaces.rb +12 -0
  29. data/lib/cassanity/argument_generators/set_clause.rb +30 -0
  30. data/lib/cassanity/argument_generators/using_clause.rb +24 -0
  31. data/lib/cassanity/argument_generators/where_clause.rb +29 -0
  32. data/lib/cassanity/argument_generators/with_clause.rb +32 -0
  33. data/lib/cassanity/column_family.rb +233 -0
  34. data/lib/cassanity/connection.rb +88 -0
  35. data/lib/cassanity/error.rb +28 -0
  36. data/lib/cassanity/executors/cassandra_cql.rb +120 -0
  37. data/lib/cassanity/keyspace.rb +118 -0
  38. data/lib/cassanity/result_transformers/column_family_select.rb +15 -0
  39. data/lib/cassanity/result_transformers/mirror.rb +12 -0
  40. data/lib/cassanity/schema.rb +26 -0
  41. data/lib/cassanity/version.rb +3 -0
  42. data/lib/cassanity.rb +5 -0
  43. data/spec/helper.rb +27 -0
  44. data/spec/integration/cassanity/column_family_spec.rb +243 -0
  45. data/spec/integration/cassanity/connection_spec.rb +87 -0
  46. data/spec/integration/cassanity/keyspace_spec.rb +64 -0
  47. data/spec/support/cassanity_helpers.rb +35 -0
  48. data/spec/unit/cassanity/argument_generators/batch_spec.rb +36 -0
  49. data/spec/unit/cassanity/argument_generators/column_family_alter_spec.rb +85 -0
  50. data/spec/unit/cassanity/argument_generators/column_family_create_spec.rb +107 -0
  51. data/spec/unit/cassanity/argument_generators/column_family_delete_spec.rb +92 -0
  52. data/spec/unit/cassanity/argument_generators/column_family_drop_spec.rb +25 -0
  53. data/spec/unit/cassanity/argument_generators/column_family_insert_spec.rb +70 -0
  54. data/spec/unit/cassanity/argument_generators/column_family_select_spec.rb +113 -0
  55. data/spec/unit/cassanity/argument_generators/column_family_truncate_spec.rb +25 -0
  56. data/spec/unit/cassanity/argument_generators/column_family_update_spec.rb +109 -0
  57. data/spec/unit/cassanity/argument_generators/index_create_spec.rb +39 -0
  58. data/spec/unit/cassanity/argument_generators/index_drop_spec.rb +14 -0
  59. data/spec/unit/cassanity/argument_generators/keyspace_create_spec.rb +53 -0
  60. data/spec/unit/cassanity/argument_generators/keyspace_drop_spec.rb +14 -0
  61. data/spec/unit/cassanity/argument_generators/keyspace_use_spec.rb +14 -0
  62. data/spec/unit/cassanity/argument_generators/keyspaces_spec.rb +12 -0
  63. data/spec/unit/cassanity/argument_generators/set_clause_spec.rb +85 -0
  64. data/spec/unit/cassanity/argument_generators/using_clause_spec.rb +44 -0
  65. data/spec/unit/cassanity/argument_generators/where_clause_spec.rb +57 -0
  66. data/spec/unit/cassanity/argument_generators/with_clause_spec.rb +63 -0
  67. data/spec/unit/cassanity/column_family_spec.rb +250 -0
  68. data/spec/unit/cassanity/connection_spec.rb +75 -0
  69. data/spec/unit/cassanity/error_spec.rb +35 -0
  70. data/spec/unit/cassanity/executors/cassandra_cql_spec.rb +178 -0
  71. data/spec/unit/cassanity/keyspace_spec.rb +137 -0
  72. data/spec/unit/cassanity/result_transformers/column_family_select_spec.rb +0 -0
  73. data/spec/unit/cassanity/result_transformers/mirror_spec.rb +12 -0
  74. data/spec/unit/cassanity/schema_spec.rb +23 -0
  75. data/spec/unit/cassanity_spec.rb +5 -0
  76. metadata +172 -0
@@ -0,0 +1,109 @@
1
+ require 'helper'
2
+ require 'cassanity/argument_generators/column_family_update'
3
+
4
+ describe Cassanity::ArgumentGenerators::ColumnFamilyUpdate do
5
+ let(:column_family_name) { 'apps' }
6
+
7
+ describe "#call" do
8
+ it "returns array of arguments" do
9
+ cql = "UPDATE #{column_family_name} SET name = ? WHERE id = ?"
10
+ expected = [cql, 'New Name', '1']
11
+ subject.call({
12
+ name: column_family_name,
13
+ set: {
14
+ name: 'New Name',
15
+ },
16
+ where: {
17
+ id: '1',
18
+ }
19
+ }).should eq(expected)
20
+ end
21
+
22
+ context "with :keyspace_name" do
23
+ it "returns array of arguments" do
24
+ cql = "UPDATE foo.#{column_family_name} SET name = ? WHERE id = ?"
25
+ expected = [cql, 'New Name', '1']
26
+ subject.call({
27
+ keyspace_name: :foo,
28
+ name: column_family_name,
29
+ set: {
30
+ name: 'New Name',
31
+ },
32
+ where: {
33
+ id: '1',
34
+ }
35
+ }).should eq(expected)
36
+ end
37
+ end
38
+
39
+ context "with :where key" do
40
+ subject {
41
+ described_class.new({
42
+ where_clause: lambda { |args|
43
+ [" WHERE id = ?", args.fetch(:where).fetch(:id)]
44
+ }
45
+ })
46
+ }
47
+
48
+ it "uses where clause to get additional cql and bound variables" do
49
+ cql = "UPDATE #{column_family_name} SET name = ? WHERE id = ?"
50
+ expected = [cql, 'New Name', '4']
51
+ subject.call({
52
+ name: column_family_name,
53
+ set: {
54
+ name: 'New Name',
55
+ },
56
+ where: {
57
+ id: '4',
58
+ }
59
+ }).should eq(expected)
60
+ end
61
+ end
62
+
63
+ context "with :set key" do
64
+ subject {
65
+ described_class.new({
66
+ set_clause: lambda { |args|
67
+ [" SET name = ?", args.fetch(:set).fetch(:name)]
68
+ }
69
+ })
70
+ }
71
+
72
+ it "uses set clause to get additional cql and bound variables" do
73
+ cql = "UPDATE #{column_family_name} SET name = ? WHERE id = ?"
74
+ expected = [cql, 'New Name', '4']
75
+ subject.call({
76
+ name: column_family_name,
77
+ set: {
78
+ name: 'New Name',
79
+ },
80
+ where: {
81
+ id: '4',
82
+ }
83
+ }).should eq(expected)
84
+ end
85
+ end
86
+
87
+ context "with :using key" do
88
+ it "returns array of arguments with cql including using" do
89
+ millis = (Time.mktime(2012, 11, 1, 14, 9, 9).to_f * 1000).to_i
90
+ cql = "UPDATE #{column_family_name} USING TTL 86400 AND TIMESTAMP #{millis} AND CONSISTENCY quorum SET name = ? WHERE id = ?"
91
+ expected = [cql, 'New Name', '1']
92
+ subject.call({
93
+ name: column_family_name,
94
+ using: {
95
+ ttl: 86400,
96
+ timestamp: millis,
97
+ consistency: 'quorum',
98
+ },
99
+ set: {
100
+ name: 'New Name',
101
+ },
102
+ where: {
103
+ id: '1',
104
+ },
105
+ }).should eq(expected)
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,39 @@
1
+ require 'helper'
2
+ require 'cassanity/argument_generators/index_create'
3
+
4
+ describe Cassanity::ArgumentGenerators::IndexCreate do
5
+ describe "#call" do
6
+ it "returns array of arguments" do
7
+ cql = "CREATE INDEX ON mutants (ability_id)"
8
+ expected = [cql]
9
+ subject.call({
10
+ column_family_name: :mutants,
11
+ column_name: :ability_id,
12
+ }).should eq(expected)
13
+ end
14
+
15
+ context "with :keyspace_name" do
16
+ it "returns array of arguments" do
17
+ cql = "CREATE INDEX ON app.mutants (ability_id)"
18
+ expected = [cql]
19
+ subject.call({
20
+ keyspace_name: :app,
21
+ column_family_name: :mutants,
22
+ column_name: :ability_id,
23
+ }).should eq(expected)
24
+ end
25
+ end
26
+
27
+ context "with :name" do
28
+ it "returns array of arguments with name in cql" do
29
+ cql = "CREATE INDEX ability_index ON mutants (ability_id)"
30
+ expected = [cql]
31
+ subject.call({
32
+ name: :ability_index,
33
+ column_family_name: :mutants,
34
+ column_name: :ability_id,
35
+ }).should eq(expected)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,14 @@
1
+ require 'helper'
2
+ require 'cassanity/argument_generators/index_drop'
3
+
4
+ describe Cassanity::ArgumentGenerators::IndexDrop do
5
+ describe "#call" do
6
+ it "returns array of arguments" do
7
+ cql = "DROP INDEX mutants_ability_id"
8
+ expected = [cql]
9
+ subject.call({
10
+ :name => :mutants_ability_id,
11
+ }).should eq(expected)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,53 @@
1
+ require 'helper'
2
+ require 'cassanity/argument_generators/keyspace_create'
3
+
4
+ describe Cassanity::ArgumentGenerators::KeyspaceCreate do
5
+ let(:keyspace_name) { 'analytics' }
6
+
7
+ describe "#call" do
8
+ context "only name" do
9
+ it "returns array of arguments" do
10
+ cql = "CREATE KEYSPACE #{keyspace_name} WITH strategy_class = ? AND strategy_options:replication_factor = ?"
11
+ expected = [cql, 'SimpleStrategy', 1]
12
+ subject.call(name: keyspace_name).should eq(expected)
13
+ end
14
+ end
15
+
16
+ context "overriding strategy_class" do
17
+ it "returns array of arguments" do
18
+ cql = "CREATE KEYSPACE #{keyspace_name} WITH strategy_class = ? AND strategy_options:replication_factor = ?"
19
+ expected = [cql, 'FooStrategy', 1]
20
+ subject.call({
21
+ name: keyspace_name,
22
+ strategy_class: 'FooStrategy',
23
+ }).should eq(expected)
24
+ end
25
+ end
26
+
27
+ context "overriding a default strategy_option" do
28
+ it "returns array of arguments" do
29
+ cql = "CREATE KEYSPACE #{keyspace_name} WITH strategy_class = ? AND strategy_options:replication_factor = ?"
30
+ expected = [cql, 'SimpleStrategy', 3]
31
+ subject.call({
32
+ name: keyspace_name,
33
+ strategy_options: {
34
+ replication_factor: 3,
35
+ }
36
+ }).should eq(expected)
37
+ end
38
+ end
39
+
40
+ context "adding new strategy_option" do
41
+ it "returns array of arguments" do
42
+ cql = "CREATE KEYSPACE #{keyspace_name} WITH strategy_class = ? AND strategy_options:replication_factor = ? AND strategy_options:batman = ?"
43
+ expected = [cql, 'SimpleStrategy', 1, 'robin']
44
+ subject.call({
45
+ name: keyspace_name,
46
+ strategy_options: {
47
+ batman: 'robin',
48
+ }
49
+ }).should eq(expected)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,14 @@
1
+ require 'helper'
2
+ require 'cassanity/argument_generators/keyspace_drop'
3
+
4
+ describe Cassanity::ArgumentGenerators::KeyspaceDrop do
5
+ let(:keyspace_name) { 'analytics' }
6
+
7
+ describe "#call" do
8
+ it "returns array of arguments" do
9
+ cql = "DROP KEYSPACE #{keyspace_name}"
10
+ expected = [cql]
11
+ subject.call(name: keyspace_name).should eq(expected)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ require 'helper'
2
+ require 'cassanity/argument_generators/keyspace_use'
3
+
4
+ describe Cassanity::ArgumentGenerators::KeyspaceUse do
5
+ let(:keyspace_name) { 'analytics' }
6
+
7
+ describe "#call" do
8
+ it "returns array of arguments" do
9
+ cql = "USE #{keyspace_name}"
10
+ expected = [cql]
11
+ subject.call(name: keyspace_name).should eq(expected)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,12 @@
1
+ require 'helper'
2
+ require 'cassanity/argument_generators/keyspaces'
3
+
4
+ describe Cassanity::ArgumentGenerators::Keyspaces do
5
+ describe "#call" do
6
+ it "returns array of arguments" do
7
+ cql = "SELECT * FROM system.schema_keyspaces"
8
+ expected = [cql]
9
+ subject.call.should eq(expected)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,85 @@
1
+ require 'helper'
2
+ require 'cassanity/argument_generators/set_clause'
3
+
4
+ describe Cassanity::ArgumentGenerators::SetClause do
5
+ describe "#call" do
6
+ it "returns array of arguments" do
7
+ subject.call({
8
+ set: {
9
+ name: 'GitHub',
10
+ }
11
+ }).should eq([
12
+ " SET name = ?",
13
+ 'GitHub',
14
+ ])
15
+ end
16
+
17
+ context "with multiple :set keys/values" do
18
+ it "returns array of arguments where each SET is comma separated" do
19
+ time = Time.now
20
+
21
+ subject.call({
22
+ set: {
23
+ name: 'GitHub',
24
+ created_at: time,
25
+ }
26
+ }).should eq([
27
+ " SET name = ?, created_at = ?",
28
+ 'GitHub',
29
+ time,
30
+ ])
31
+ end
32
+ end
33
+
34
+ context "with counter update" do
35
+ it "returns array of arguments where counter SET is correct" do
36
+ subject.call(set: {views: 'views + 5'}).
37
+ should eq([" SET views = views + 5"])
38
+ end
39
+
40
+ it "works with no spaces" do
41
+ subject.call(set: {views: 'views+5'}).
42
+ should eq([" SET views = views+5"])
43
+ end
44
+
45
+ it "works with one or more spaces before the operator" do
46
+ subject.call(set: {views: 'views +5'}).
47
+ should eq([" SET views = views +5"])
48
+
49
+ subject.call(set: {views: 'views +5'}).
50
+ should eq([" SET views = views +5"])
51
+ end
52
+
53
+ it "works with one or more spaces after the operator" do
54
+ subject.call(set: {views: 'views+ 5'}).
55
+ should eq([" SET views = views+ 5"])
56
+
57
+ subject.call(set: {views: 'views+ 5'}).
58
+ should eq([" SET views = views+ 5"])
59
+ end
60
+
61
+ it "works with spaces after before the key" do
62
+ subject.call(set: {views: ' views + 5'}).
63
+ should eq([" SET views = views + 5"])
64
+ end
65
+
66
+ it "works with spaces after the number" do
67
+ subject.call(set: {views: 'views + 5 '}).
68
+ should eq([" SET views = views + 5 "])
69
+
70
+ subject.call(set: {views: 'views + 5 '}).
71
+ should eq([" SET views = views + 5 "])
72
+ end
73
+
74
+ it "works with negative operator" do
75
+ subject.call(set: {views: 'views - 5'}).
76
+ should eq([" SET views = views - 5"])
77
+ end
78
+
79
+ it "works with multiple digit numbers" do
80
+ subject.call(set: {views: 'views - 52737237'}).
81
+ should eq([" SET views = views - 52737237"])
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,44 @@
1
+ require 'helper'
2
+ require 'cassanity/argument_generators/using_clause'
3
+
4
+ describe Cassanity::ArgumentGenerators::UsingClause do
5
+ describe "#call" do
6
+ context "with single :using option" do
7
+ it "returns array of arguments" do
8
+ subject.call({
9
+ using: {
10
+ ttl: 500,
11
+ }
12
+ }).should eq([
13
+ " USING TTL 500",
14
+ ])
15
+ end
16
+ end
17
+
18
+ context "with multiple :using option" do
19
+ it "returns array of arguments" do
20
+ subject.call({
21
+ using: {
22
+ ttl: 500,
23
+ consistency: 'quorum',
24
+ timestamp: 1234,
25
+ }
26
+ }).should eq([
27
+ " USING TTL 500 AND CONSISTENCY quorum AND TIMESTAMP 1234",
28
+ ])
29
+ end
30
+ end
31
+
32
+ context "with no arguments" do
33
+ it "returns array of arguments where only item is empty string" do
34
+ subject.call.should eq([""])
35
+ end
36
+ end
37
+
38
+ context "with empty arguments" do
39
+ it "returns array of arguments where only item is empty string" do
40
+ subject.call({}).should eq([""])
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,57 @@
1
+ require 'helper'
2
+ require 'cassanity/argument_generators/where_clause'
3
+
4
+ describe Cassanity::ArgumentGenerators::WhereClause do
5
+ describe "#call" do
6
+ it "returns array of arguments" do
7
+ subject.call({
8
+ where: {
9
+ id: '1',
10
+ }
11
+ }).should eq([
12
+ " WHERE id = ?",
13
+ '1',
14
+ ])
15
+ end
16
+
17
+ context "with nil where" do
18
+ it "returns array with empty string" do
19
+ subject.call.should eq([""])
20
+ end
21
+ end
22
+
23
+ context "with empty where" do
24
+ it "returns array with empty string" do
25
+ subject.call(where: {}).should eq([""])
26
+ end
27
+ end
28
+
29
+ context "with array value for a where" do
30
+ it "returns array of arguments using IN for key with array value" do
31
+ subject.call({
32
+ where: {
33
+ id: ['1', '2', '3'],
34
+ }
35
+ }).should eq([
36
+ " WHERE id IN (?)",
37
+ ['1', '2', '3'],
38
+ ])
39
+ end
40
+ end
41
+
42
+ context "with multiple where values" do
43
+ it "returns array of arguments with AND separating where keys" do
44
+ subject.call({
45
+ where: {
46
+ bucket: '2012',
47
+ id: '1',
48
+ }
49
+ }).should eq([
50
+ " WHERE bucket = ? AND id = ?",
51
+ '2012',
52
+ '1',
53
+ ])
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,63 @@
1
+ require 'helper'
2
+ require 'cassanity/argument_generators/with_clause'
3
+
4
+ describe Cassanity::ArgumentGenerators::WithClause do
5
+ describe "#call" do
6
+ context "with single :with option" do
7
+ it "returns array of arguments" do
8
+ subject.call({
9
+ with: {
10
+ comment: 'Just testing',
11
+ }
12
+ }).should eq([
13
+ " WITH comment = ?",
14
+ 'Just testing',
15
+ ])
16
+ end
17
+ end
18
+
19
+ context "with multiple :with option" do
20
+ it "returns array of arguments" do
21
+ subject.call({
22
+ with: {
23
+ comment: 'Just testing',
24
+ read_repair_chance: 0.2,
25
+ }
26
+ }).should eq([
27
+ " WITH comment = ? AND read_repair_chance = ?",
28
+ 'Just testing',
29
+ 0.2,
30
+ ])
31
+ end
32
+ end
33
+
34
+ context "when using :with option that has sub options" do
35
+ it "returns array of arguments" do
36
+ subject.call({
37
+ with: {
38
+ compaction_strategy_options: {
39
+ min_compaction_threshold: 6,
40
+ max_compaction_threshold: 40,
41
+ },
42
+ }
43
+ }).should eq([
44
+ " WITH compaction_strategy_options:min_compaction_threshold = ? AND compaction_strategy_options:max_compaction_threshold = ?",
45
+ 6,
46
+ 40,
47
+ ])
48
+ end
49
+ end
50
+
51
+ context "with no arguments" do
52
+ it "returns array of arguments where only item is empty string" do
53
+ subject.call.should eq([""])
54
+ end
55
+ end
56
+
57
+ context "with empty arguments" do
58
+ it "returns array of arguments where only item is empty string" do
59
+ subject.call({}).should eq([""])
60
+ end
61
+ end
62
+ end
63
+ end