cassandra-cql 1.1.5 → 1.2.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.
- data/.travis.yml +9 -12
- data/Gemfile +1 -1
- data/README.md +4 -0
- data/Rakefile +29 -6
- data/lib/cassandra-cql.rb +3 -0
- data/lib/cassandra-cql/1.2.rb +8 -0
- data/lib/cassandra-cql/1.2/result.rb +6 -0
- data/lib/cassandra-cql/1.2/statement.rb +6 -0
- data/lib/cassandra-cql/collections/list.rb +17 -0
- data/lib/cassandra-cql/collections/map.rb +26 -0
- data/lib/cassandra-cql/collections/set.rb +10 -0
- data/lib/cassandra-cql/database.rb +11 -2
- data/lib/cassandra-cql/result.rb +1 -1
- data/lib/cassandra-cql/schema.rb +18 -1
- data/lib/cassandra-cql/statement.rb +20 -9
- data/lib/cassandra-cql/version.rb +2 -2
- data/spec/comparator_spec.rb +2 -2
- data/spec/conf/1.1/cassandra.in.sh +41 -0
- data/spec/conf/1.1/cassandra.yaml +567 -0
- data/spec/conf/1.1/log4j-server.properties +44 -0
- data/spec/conf/1.1/schema.json +72 -0
- data/spec/conf/1.1/schema.txt +57 -0
- data/spec/conf/1.2/cassandra.in.sh +41 -0
- data/spec/conf/1.2/cassandra.yaml +643 -0
- data/spec/conf/1.2/log4j-server.properties +44 -0
- data/spec/conf/1.2/schema.json +72 -0
- data/spec/conf/1.2/schema.txt +57 -0
- data/spec/misc_spec.rb +6 -4
- data/spec/result_spec.rb +16 -2
- data/spec/row_spec.rb +43 -5
- data/spec/rowkey_spec.rb +2 -2
- data/spec/spec_helper.rb +66 -12
- data/spec/statement_spec.rb +41 -16
- data/spec/validation_spec.rb +5 -4
- data/vendor/1.2/gen-rb/cassandra.rb +3013 -0
- data/vendor/1.2/gen-rb/cassandra_constants.rb +13 -0
- data/vendor/1.2/gen-rb/cassandra_types.rb +966 -0
- metadata +21 -5
@@ -0,0 +1,44 @@
|
|
1
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
2
|
+
# or more contributor license agreements. See the NOTICE file
|
3
|
+
# distributed with this work for additional information
|
4
|
+
# regarding copyright ownership. The ASF licenses this file
|
5
|
+
# to you under the Apache License, Version 2.0 (the
|
6
|
+
# "License"); you may not use this file except in compliance
|
7
|
+
# with the License. You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
# for production, you should probably set pattern to %c instead of %l.
|
18
|
+
# (%l is slower.)
|
19
|
+
|
20
|
+
# output messages into a rolling log file as well as stdout
|
21
|
+
log4j.rootLogger=INFO,stdout,R
|
22
|
+
|
23
|
+
# stdout
|
24
|
+
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
25
|
+
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
26
|
+
log4j.appender.stdout.layout.ConversionPattern=%5p %d{HH:mm:ss,SSS} %m%n
|
27
|
+
|
28
|
+
# rolling log file
|
29
|
+
log4j.appender.R=org.apache.log4j.RollingFileAppender
|
30
|
+
log4j.appender.R.maxFileSize=20MB
|
31
|
+
log4j.appender.R.maxBackupIndex=50
|
32
|
+
log4j.appender.R.layout=org.apache.log4j.PatternLayout
|
33
|
+
log4j.appender.R.layout.ConversionPattern=%5p [%t] %d{ISO8601} %F (line %L) %m%n
|
34
|
+
# Edit the next line to point to your logs directory
|
35
|
+
log4j.appender.R.File=/var/log/cassandra/system.log
|
36
|
+
|
37
|
+
# Application logging options
|
38
|
+
#log4j.logger.org.apache.cassandra=DEBUG
|
39
|
+
#log4j.logger.org.apache.cassandra.db=DEBUG
|
40
|
+
#log4j.logger.org.apache.cassandra.service.StorageProxy=DEBUG
|
41
|
+
|
42
|
+
# Adding this to avoid thrift logging disconnect errors.
|
43
|
+
log4j.logger.org.apache.thrift.server.TNonblockingServer=ERROR
|
44
|
+
|
@@ -0,0 +1,72 @@
|
|
1
|
+
{"Twitter":{
|
2
|
+
"Users":{
|
3
|
+
"comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
|
4
|
+
"column_type":"Standard"},
|
5
|
+
"UserAudits":{
|
6
|
+
"comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
|
7
|
+
"column_type":"Standard"},
|
8
|
+
"UserCounters":{
|
9
|
+
"comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
|
10
|
+
"column_type":"Standard",
|
11
|
+
"default_validation_class":"CounterColumnType"},
|
12
|
+
"UserCounterAggregates":{
|
13
|
+
"subcomparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
|
14
|
+
"comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
|
15
|
+
"column_type":"Super",
|
16
|
+
"default_validation_class":"CounterColumnType"},
|
17
|
+
"UserRelationships":{
|
18
|
+
"subcomparator_type":"org.apache.cassandra.db.marshal.TimeUUIDType",
|
19
|
+
"comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
|
20
|
+
"column_type":"Super"},
|
21
|
+
"Usernames":{
|
22
|
+
"comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
|
23
|
+
"column_type":"Standard"},
|
24
|
+
"Statuses":{
|
25
|
+
"comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
|
26
|
+
"column_type":"Standard"},
|
27
|
+
"StatusAudits":{
|
28
|
+
"comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
|
29
|
+
"column_type":"Standard"},
|
30
|
+
"StatusRelationships":{
|
31
|
+
"subcomparator_type":"org.apache.cassandra.db.marshal.TimeUUIDType",
|
32
|
+
"comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
|
33
|
+
"column_type":"Super"},
|
34
|
+
"Indexes":{
|
35
|
+
"comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
|
36
|
+
"column_type":"Super"},
|
37
|
+
"TimelinishThings":{
|
38
|
+
"comparator_type":"org.apache.cassandra.db.marshal.BytesType",
|
39
|
+
"column_type":"Standard"}
|
40
|
+
},
|
41
|
+
"Multiblog":{
|
42
|
+
"Blogs":{
|
43
|
+
"comparator_type":"org.apache.cassandra.db.marshal.TimeUUIDType",
|
44
|
+
"column_type":"Standard"},
|
45
|
+
"Comments":{
|
46
|
+
"comparator_type":"org.apache.cassandra.db.marshal.TimeUUIDType",
|
47
|
+
"column_type":"Standard"}
|
48
|
+
},
|
49
|
+
"MultiblogLong":{
|
50
|
+
"Blogs":{
|
51
|
+
"comparator_type":"org.apache.cassandra.db.marshal.LongType",
|
52
|
+
"column_type":"Standard"},
|
53
|
+
"Comments":{
|
54
|
+
"comparator_type":"org.apache.cassandra.db.marshal.LongType",
|
55
|
+
"column_type":"Standard"}
|
56
|
+
},
|
57
|
+
"TypeConversions":{
|
58
|
+
"UUIDColumnConversion":{
|
59
|
+
"comparator_type":"org.apache.cassandra.db.marshal.TimeUUIDType",
|
60
|
+
"column_type":"Standard"},
|
61
|
+
"SuperUUID":{
|
62
|
+
"subcomparator_type":"org.apache.cassandra.db.marshal.TimeUUIDType",
|
63
|
+
"comparator_type":"org.apache.cassandra.db.marshal.TimeUUIDType",
|
64
|
+
"column_type":"Super"},
|
65
|
+
"CompositeColumnConversion":{
|
66
|
+
"comparator_type":"org.apache.cassandra.db.marshal.CompositeType(org.apache.cassandra.db.marshal.IntegerType,org.apache.cassandra.db.marshal.UTF8Type)",
|
67
|
+
"column_type":"Standard"},
|
68
|
+
"DynamicComposite":{
|
69
|
+
"comparator_type":"org.apache.cassandra.db.marshal.DynamicCompositeType(u=>org.apache.cassandra.db.marshal.UUIDType,t=>org.apache.cassandra.db.marshal.TimeUUIDType,s=>org.apache.cassandra.db.marshal.UTF8Type,b=>org.apache.cassandra.db.marshal.BytesType,a=>org.apache.cassandra.db.marshal.AsciiType,l=>org.apache.cassandra.db.marshal.LongType,x=>org.apache.cassandra.db.marshal.LexicalUUIDType,i=>org.apache.cassandra.db.marshal.IntegerType)",
|
70
|
+
"column_type":"Standard"}
|
71
|
+
}
|
72
|
+
}
|
@@ -0,0 +1,57 @@
|
|
1
|
+
create keyspace Twitter with
|
2
|
+
placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' AND
|
3
|
+
strategy_options = {replication_factor:1};
|
4
|
+
use Twitter;
|
5
|
+
create column family Users with comparator = 'UTF8Type';
|
6
|
+
create column family UserAudits with comparator = 'UTF8Type';
|
7
|
+
create column family UserCounters with comparator = 'UTF8Type' and
|
8
|
+
default_validation_class = CounterColumnType;
|
9
|
+
create column family UserCounterAggregates with column_type = 'Super'
|
10
|
+
and comparator = 'UTF8Type' and
|
11
|
+
subcomparator = 'UTF8Type' and
|
12
|
+
default_validation_class = CounterColumnType;
|
13
|
+
create column family UserRelationships with
|
14
|
+
comparator = 'UTF8Type' and
|
15
|
+
column_type = 'Super' and
|
16
|
+
subcomparator = 'TimeUUIDType';
|
17
|
+
create column family Usernames with comparator = 'UTF8Type';
|
18
|
+
create column family Statuses
|
19
|
+
with comparator = 'UTF8Type'
|
20
|
+
and column_metadata = [
|
21
|
+
{column_name: 'tags', validation_class: 'BytesType', index_type: 'KEYS'}
|
22
|
+
];
|
23
|
+
create column family StatusAudits with comparator = 'UTF8Type';
|
24
|
+
create column family StatusRelationships with
|
25
|
+
comparator = 'UTF8Type' and
|
26
|
+
column_type = 'Super' and
|
27
|
+
subcomparator = 'TimeUUIDType';
|
28
|
+
create column family Indexes with
|
29
|
+
comparator = 'UTF8Type' and
|
30
|
+
column_type = 'Super';
|
31
|
+
create column family TimelinishThings with
|
32
|
+
comparator = 'BytesType';
|
33
|
+
|
34
|
+
create keyspace Multiblog with
|
35
|
+
placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' AND
|
36
|
+
strategy_options = {replication_factor:1};
|
37
|
+
use Multiblog;
|
38
|
+
create column family Blogs with comparator = 'TimeUUIDType';
|
39
|
+
create column family Comments with comparator = 'TimeUUIDType';
|
40
|
+
|
41
|
+
|
42
|
+
create keyspace MultiblogLong with
|
43
|
+
placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' AND
|
44
|
+
strategy_options = {replication_factor:1};
|
45
|
+
use MultiblogLong;
|
46
|
+
create column family Blogs with comparator = 'LongType';
|
47
|
+
create column family Comments with comparator = 'LongType';
|
48
|
+
|
49
|
+
create keyspace TypeConversions with
|
50
|
+
placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' AND
|
51
|
+
strategy_options = {replication_factor:1};
|
52
|
+
use TypeConversions;
|
53
|
+
create column family UUIDColumnConversion with comparator = TimeUUIDType;
|
54
|
+
create column family SuperUUID with comparator = TimeUUIDType and column_type = Super;
|
55
|
+
create column family CompositeColumnConversion with comparator = 'CompositeType(IntegerType, UTF8Type)';
|
56
|
+
create column family DynamicComposite with comparator ='DynamicCompositeType
|
57
|
+
(a=>AsciiType,b=>BytesType,i=>IntegerType,x=>LexicalUUIDType,l=>LongType,t=>TimeUUIDType,s=>UTF8Type,u=>UUIDType)';
|
data/spec/misc_spec.rb
CHANGED
@@ -4,7 +4,7 @@ include CassandraCQL
|
|
4
4
|
describe "Miscellaneous tests that handle specific failures/regressions" do
|
5
5
|
before(:each) do
|
6
6
|
@connection = setup_cassandra_connection
|
7
|
-
@connection
|
7
|
+
drop_column_family_if_exists(@connection, 'misc_tests')
|
8
8
|
@connection.execute("CREATE COLUMNFAMILY misc_tests (id text PRIMARY KEY)")
|
9
9
|
end
|
10
10
|
|
@@ -12,7 +12,7 @@ describe "Miscellaneous tests that handle specific failures/regressions" do
|
|
12
12
|
before(:each) do
|
13
13
|
@connection.execute("ALTER COLUMNFAMILY misc_tests ADD test_column ascii")
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
it "should be consistent with ascii-encoded text" do
|
17
17
|
@connection.execute("INSERT INTO misc_tests (id, test_column) VALUES (?, ?)", 'test', 'test_column').should be_nil
|
18
18
|
row = @connection.execute("SELECT test_column FROM misc_tests WHERE id=?", 'test').fetch
|
@@ -25,11 +25,13 @@ describe "Miscellaneous tests that handle specific failures/regressions" do
|
|
25
25
|
|
26
26
|
context "with unvalidatable data" do
|
27
27
|
before(:each) do
|
28
|
+
@connection.execute("ALTER COLUMNFAMILY misc_tests ADD good_column varchar")
|
29
|
+
@connection.execute("ALTER COLUMNFAMILY misc_tests ADD bad_column varchar")
|
28
30
|
@connection.execute("INSERT INTO misc_tests (id, good_column, bad_column) VALUES (?, ?, ?)", 'test', 'blah', '')
|
29
|
-
@connection.execute("ALTER COLUMNFAMILY misc_tests
|
31
|
+
@connection.execute("ALTER COLUMNFAMILY misc_tests ALTER bad_column TYPE int")
|
30
32
|
@row = @connection.execute("SELECT good_column, bad_column FROM misc_tests WHERE id=?", 'test').fetch
|
31
33
|
end
|
32
|
-
|
34
|
+
|
33
35
|
it "should have valid column_names" do
|
34
36
|
@row.column_names.should eq ['good_column', 'bad_column']
|
35
37
|
end
|
data/spec/result_spec.rb
CHANGED
@@ -11,10 +11,12 @@ describe "void results" do
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
|
14
|
+
# CQL3 does not directly model wide rows as sparse rows, so this test is only
|
15
|
+
# needed for CQL2
|
16
|
+
describe "sparse row results", :cql_version => '2.0.0' do
|
15
17
|
before(:each) do
|
16
18
|
@connection = setup_cassandra_connection
|
17
|
-
if
|
19
|
+
if !column_family_exists?(@connection, 'sparse_results')
|
18
20
|
@connection.execute("CREATE COLUMNFAMILY sparse_results (id varchar PRIMARY KEY)")
|
19
21
|
else
|
20
22
|
@connection.execute("TRUNCATE sparse_results")
|
@@ -43,6 +45,18 @@ end
|
|
43
45
|
describe "row results" do
|
44
46
|
before(:each) do
|
45
47
|
@connection = setup_cassandra_connection
|
48
|
+
drop_column_family_if_exists(@connection, 'sparse_results')
|
49
|
+
@connection.execute(<<-CQL)
|
50
|
+
CREATE TABLE sparse_results (
|
51
|
+
id varchar PRIMARY KEY,
|
52
|
+
col1 varchar,
|
53
|
+
col2 varchar,
|
54
|
+
col3 varchar,
|
55
|
+
col4 varchar,
|
56
|
+
col5 varchar,
|
57
|
+
col6 varchar
|
58
|
+
)
|
59
|
+
CQL
|
46
60
|
@connection.execute("INSERT INTO sparse_results (id, col1, col2, col3) VALUES (?, ?, ?, ?)", 'key1', 'val1', 'val2', 'val3').should be_nil
|
47
61
|
@connection.execute("INSERT INTO sparse_results (id, col4, col5, col6) VALUES (?, ?, ?, ?)", 'key2', 'val4', 'val5', 'val6').should be_nil
|
48
62
|
@result = @connection.execute("SELECT col1, col2, col3, col4 FROM sparse_results")
|
data/spec/row_spec.rb
CHANGED
@@ -6,12 +6,10 @@ describe "basic methods" do
|
|
6
6
|
context 'with basic column family' do
|
7
7
|
before(:each) do
|
8
8
|
@connection = setup_cassandra_connection
|
9
|
-
|
10
|
-
@connection.execute("DROP COLUMNFAMILY basic_methods")
|
11
|
-
end
|
9
|
+
drop_column_family_if_exists(@connection, 'basic_methods')
|
12
10
|
@connection.execute("CREATE COLUMNFAMILY basic_methods (id varchar PRIMARY KEY, created_at uuid, default_column varchar, name varchar, serial int)")
|
13
11
|
|
14
|
-
@connection.execute("INSERT INTO basic_methods (id, created_at, name, serial, default_column) VALUES (?, ?, ?, ?, ?)", 'test',
|
12
|
+
@connection.execute("INSERT INTO basic_methods (id, created_at, name, serial, default_column) VALUES (?, ?, ?, ?, ?)", 'test', CassandraCQL::UUID.new, 'name', 12345, 'snork')
|
15
13
|
@row = @connection.execute("SELECT * FROM basic_methods WHERE id=?", "test").fetch
|
16
14
|
end
|
17
15
|
|
@@ -48,7 +46,7 @@ describe "basic methods" do
|
|
48
46
|
end
|
49
47
|
end
|
50
48
|
|
51
|
-
context 'with a column family with int comparators' do
|
49
|
+
context 'with a column family with int comparators', :cql_version => '2.0.0' do
|
52
50
|
before(:each) do
|
53
51
|
@connection = setup_cassandra_connection
|
54
52
|
if @connection.schema.column_family_names.include?('int_comparator')
|
@@ -73,4 +71,44 @@ describe "basic methods" do
|
|
73
71
|
end
|
74
72
|
end
|
75
73
|
end
|
74
|
+
|
75
|
+
context 'collections', :cql_version => '3.0.0' do
|
76
|
+
before(:each) do
|
77
|
+
@connection = setup_cassandra_connection
|
78
|
+
if column_family_exists?(@connection, 'collections')
|
79
|
+
@connection.execute("DROP COLUMNFAMILY collections")
|
80
|
+
end
|
81
|
+
@connection.execute(<<-CQL)
|
82
|
+
CREATE COLUMNFAMILY collections (
|
83
|
+
key text PRIMARY KEY,
|
84
|
+
mylist LIST <int>,
|
85
|
+
myset SET <varchar>,
|
86
|
+
mymap MAP <uuid,timestamp>
|
87
|
+
)
|
88
|
+
CQL
|
89
|
+
|
90
|
+
@map = {
|
91
|
+
CassandraCQL::UUID.new => Time.at(Time.now.to_i),
|
92
|
+
CassandraCQL::UUID.new => Time.at(Time.now.to_i) - 60
|
93
|
+
}
|
94
|
+
|
95
|
+
@connection.execute(
|
96
|
+
"INSERT INTO collections (key, mylist, myset, mymap) VALUES (?, [?], {?}, {?:?,?:?})",
|
97
|
+
'test', [1, 2, 3], ['some', 'set'], *@map.to_a.flatten)
|
98
|
+
|
99
|
+
@row = @connection.execute("SELECT * FROM collections WHERE key=?", "test").fetch
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'should return list' do
|
103
|
+
@row.to_hash['mylist'].should == [1, 2, 3]
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'should return set' do
|
107
|
+
@row.to_hash['myset'].should == Set['some', 'set']
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'should return map' do
|
111
|
+
@row.to_hash['mymap'].should == @map
|
112
|
+
end
|
113
|
+
end
|
76
114
|
end
|
data/spec/rowkey_spec.rb
CHANGED
@@ -14,7 +14,7 @@ describe "Validation Roundtrip tests" do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def create_column_family(name, test_row_key_type)
|
17
|
-
if
|
17
|
+
if !column_family_exists?(@connection, name)
|
18
18
|
@connection.execute("CREATE COLUMNFAMILY #{name} (id #{test_row_key_type} PRIMARY KEY, test_column text)")
|
19
19
|
end
|
20
20
|
end
|
@@ -230,4 +230,4 @@ describe "Validation Roundtrip tests" do
|
|
230
230
|
test_for_value(2**256)
|
231
231
|
end
|
232
232
|
end
|
233
|
-
end
|
233
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -11,24 +11,78 @@ require 'yaml'
|
|
11
11
|
require 'rspec'
|
12
12
|
|
13
13
|
CASSANDRA_VERSION = ENV['CASSANDRA_VERSION'] || '1.1' unless defined?(CASSANDRA_VERSION)
|
14
|
+
CQL_VERSION = ENV['CQL_VERSION'] || '2.0.0'
|
15
|
+
USE_CQL3 = CQL_VERSION.split('.').first.to_i == 3
|
14
16
|
|
15
17
|
require "cassandra-cql/#{CASSANDRA_VERSION}"
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
file
|
19
|
+
module Helpers
|
20
|
+
def yaml_fixture(file)
|
21
|
+
if file.kind_of?(Symbol)
|
22
|
+
file = "#{file}.yaml"
|
23
|
+
elsif file !~ /\.yaml$/
|
24
|
+
file = "#{file}.yaml"
|
25
|
+
end
|
26
|
+
YAML::load_file(File.dirname(__FILE__) + "/fixtures/#{file}")
|
27
|
+
end
|
28
|
+
|
29
|
+
def setup_cassandra_connection
|
30
|
+
host = ENV['CASSANDRA_CQL_HOST'] || '127.0.0.1'
|
31
|
+
port = ENV['CASSANDRA_CQL_PORT'] || 9160
|
32
|
+
|
33
|
+
cassandra_cql_options = {}
|
34
|
+
if CASSANDRA_VERSION >= '1.2'
|
35
|
+
cassandra_cql_options.merge!(:cql_version => CQL_VERSION)
|
36
|
+
end
|
37
|
+
|
38
|
+
keyspace_name = "cassandra_cql_test_keyspace_#{CASSANDRA_VERSION.gsub(/\D/, '')}_#{CQL_VERSION.gsub(/\D/, '')}"
|
39
|
+
connection = CassandraCQL::Database.new(["#{host}:#{port}"], cassandra_cql_options, :retries => 5, :timeout => 5)
|
40
|
+
if !connection.keyspaces.map(&:name).include?(keyspace_name)
|
41
|
+
create_keyspace(connection, keyspace_name)
|
42
|
+
end
|
43
|
+
connection.execute("USE #{keyspace_name}")
|
44
|
+
|
45
|
+
connection
|
46
|
+
end
|
47
|
+
|
48
|
+
def drop_column_family_if_exists(connection, cf)
|
49
|
+
if column_family_exists?(connection, cf)
|
50
|
+
connection.execute("DROP COLUMNFAMILY #{cf}")
|
51
|
+
end
|
22
52
|
end
|
23
|
-
YAML::load_file(File.dirname(__FILE__) + "/fixtures/#{file}")
|
24
53
|
end
|
25
54
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
connection.execute("CREATE KEYSPACE CassandraCQLTestKeyspace WITH strategy_class='org.apache.cassandra.locator.SimpleStrategy' AND strategy_options:replication_factor=1")
|
55
|
+
module Cql2Helpers
|
56
|
+
def column_family_exists?(connection, cf)
|
57
|
+
@connection.schema.column_family_names.include?(cf.to_s)
|
30
58
|
end
|
31
|
-
connection.execute("USE CassandraCQLTestKeyspace")
|
32
59
|
|
33
|
-
connection
|
60
|
+
def create_keyspace(connection, ks)
|
61
|
+
connection.execute("CREATE KEYSPACE #{ks} WITH strategy_class='org.apache.cassandra.locator.SimpleStrategy' AND strategy_options:replication_factor=1")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
module Cql3Helpers
|
66
|
+
def column_family_exists?(connection, cf)
|
67
|
+
connection.execute(<<-CQL, connection.keyspace, cf).fetch_row
|
68
|
+
SELECT * FROM system.schema_columnfamilies
|
69
|
+
WHERE keyspace_name = ? AND columnfamily_name = ?
|
70
|
+
CQL
|
71
|
+
end
|
72
|
+
|
73
|
+
def create_keyspace(connection, ks)
|
74
|
+
connection.execute("CREATE KEYSPACE #{ks} WITH REPLICATION = {'class': 'SimpleStrategy', 'replication_factor': 1}")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
RSpec.configure do |config|
|
79
|
+
config.filter_run_excluding :cql_version =>
|
80
|
+
lambda { |version| version != CQL_VERSION }
|
81
|
+
|
82
|
+
config.include Helpers
|
83
|
+
if CQL_VERSION == '3.0.0'
|
84
|
+
config.include Cql3Helpers
|
85
|
+
else
|
86
|
+
config.include Cql2Helpers
|
87
|
+
end
|
34
88
|
end
|
data/spec/statement_spec.rb
CHANGED
@@ -40,8 +40,8 @@ describe "execute" do
|
|
40
40
|
context "when performing void-returning column_family operations" do
|
41
41
|
before(:each) do
|
42
42
|
@connection = setup_cassandra_connection
|
43
|
-
if
|
44
|
-
@connection.execute("CREATE COLUMNFAMILY colfam_ops (id varchar PRIMARY KEY)")
|
43
|
+
if !column_family_exists?(@connection, 'colfam_ops')
|
44
|
+
@connection.execute("CREATE COLUMNFAMILY colfam_ops (id varchar PRIMARY KEY, column varchar)")
|
45
45
|
else
|
46
46
|
@connection.execute("TRUNCATE colfam_ops")
|
47
47
|
end
|
@@ -70,29 +70,53 @@ describe "escape" do
|
|
70
70
|
end
|
71
71
|
|
72
72
|
describe "quote" do
|
73
|
+
|
73
74
|
context "with a string" do
|
74
75
|
it "should add quotes" do
|
75
|
-
Statement.quote("test").should eq("'test'")
|
76
|
+
Statement.quote("test", USE_CQL3).should eq("'test'")
|
76
77
|
end
|
77
78
|
end
|
78
79
|
|
79
80
|
context "with an integer" do
|
80
81
|
it "should not add quotes" do
|
81
|
-
Statement.quote(15).should eq(15)
|
82
|
+
Statement.quote(15, USE_CQL3).should eq("15")
|
82
83
|
end
|
83
84
|
end
|
84
85
|
|
85
86
|
context "with an array" do
|
86
87
|
it "should return a comma-separated list" do
|
87
|
-
Statement.quote([1, 2, 3]).should eq("1,2,3")
|
88
|
-
Statement.quote(["a", "b''", "c"]).should eq("'a','b''','c'")
|
88
|
+
Statement.quote([1, 2, 3], USE_CQL3).should eq("1,2,3")
|
89
|
+
Statement.quote(["a", "b''", "c"], USE_CQL3).should eq("'a','b''','c'")
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "with a big decimal" do
|
94
|
+
let :big_decimal do
|
95
|
+
BigDecimal.new('129182739481237481341234123411.1029348102934810293481039')
|
96
|
+
end
|
97
|
+
let :result do
|
98
|
+
'0.1291827394812374813412341234111029348102934810293481039E30'
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should add quotes", cql_version: '2.0.0' do
|
102
|
+
Statement.quote(BigDecimal.new(big_decimal), USE_CQL3).should eq("'#{result}'")
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should not add quotes", cql_version: '3.0.0' do
|
106
|
+
Statement.quote(big_decimal, USE_CQL3).should eq(result)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
context "with a boolean" do
|
110
|
+
it "should not add quotes" do
|
111
|
+
Statement.quote(true, USE_CQL3).should eq("true")
|
112
|
+
Statement.quote(false, USE_CQL3).should eq("false")
|
89
113
|
end
|
90
114
|
end
|
91
115
|
|
92
116
|
context "with an unsupported object" do
|
93
117
|
it "should raise an exception" do
|
94
118
|
expect {
|
95
|
-
Statement.quote(Time.new)
|
119
|
+
Statement.quote(Time.new, USE_CQL3)
|
96
120
|
}.to raise_error(CassandraCQL::Error::UnescapableObject)
|
97
121
|
end
|
98
122
|
end
|
@@ -126,7 +150,7 @@ describe "cast_to_cql" do
|
|
126
150
|
it "should return the a guid" do
|
127
151
|
uuid = UUID.new
|
128
152
|
guid = Statement.cast_to_cql(uuid)
|
129
|
-
guid.should eq(uuid
|
153
|
+
guid.should eq(uuid)
|
130
154
|
end
|
131
155
|
end
|
132
156
|
|
@@ -134,7 +158,7 @@ describe "cast_to_cql" do
|
|
134
158
|
it "should return the guid" do
|
135
159
|
uuid = SimpleUUID::UUID.new
|
136
160
|
guid = Statement.cast_to_cql(uuid)
|
137
|
-
guid.should eq(uuid
|
161
|
+
guid.should eq(uuid)
|
138
162
|
end
|
139
163
|
end
|
140
164
|
|
@@ -183,40 +207,41 @@ describe "cast_to_cql" do
|
|
183
207
|
end
|
184
208
|
|
185
209
|
describe "sanitize" do
|
210
|
+
|
186
211
|
context "with no bind vars" do
|
187
212
|
it "should return itself" do
|
188
|
-
Statement.sanitize("use keyspace").should eq("use keyspace")
|
213
|
+
Statement.sanitize("use keyspace", [], USE_CQL3).should eq("use keyspace")
|
189
214
|
end
|
190
215
|
end
|
191
216
|
|
192
217
|
context "when expecting bind vars" do
|
193
218
|
it "should raise an exception with bind variable mismatch" do
|
194
219
|
expect {
|
195
|
-
Statement.sanitize("use keyspace ?", ['too', 'many'])
|
220
|
+
Statement.sanitize("use keyspace ?", ['too', 'many'], USE_CQL3)
|
196
221
|
}.to raise_error(Error::InvalidBindVariable)
|
197
222
|
end
|
198
223
|
|
199
224
|
it "should not raise an exception with matching bind vars" do
|
200
225
|
expect {
|
201
|
-
Statement.sanitize("use keyspace ?", ["test"]).should eq("use keyspace 'test'")
|
226
|
+
Statement.sanitize("use keyspace ?", ["test"], USE_CQL3).should eq("use keyspace 'test'")
|
202
227
|
}.to_not raise_error(Error::InvalidBindVariable)
|
203
228
|
end
|
204
229
|
|
205
230
|
it "should have bind vars in the right order" do
|
206
231
|
expect {
|
207
|
-
Statement.sanitize("use keyspace ? with randomness (?)", ["test", "stuff"]).should eq("use keyspace 'test' with randomness ('stuff')")
|
232
|
+
Statement.sanitize("use keyspace ? with randomness (?)", ["test", "stuff"], USE_CQL3).should eq("use keyspace 'test' with randomness ('stuff')")
|
208
233
|
}.to_not raise_error(Error::InvalidBindVariable)
|
209
234
|
end
|
210
235
|
|
211
236
|
it "should not double-escape the single quotes in your string" do
|
212
237
|
Statement.sanitize(
|
213
|
-
"insert into keyspace (key, ?) values (?)", ["vanilla", %Q{I\'m a string with \'cool\' quotes}]
|
238
|
+
"insert into keyspace (key, ?) values (?)", ["vanilla", %Q{I\'m a string with \'cool\' quotes}], USE_CQL3
|
214
239
|
).should eq("insert into keyspace (key, 'vanilla') values ('I''m a string with ''cool'' quotes')")
|
215
240
|
end
|
216
241
|
|
217
242
|
it "should handle numbers and stuff appropriately" do
|
218
243
|
Statement.sanitize(
|
219
|
-
"insert into keyspace (key, ?) values (?)", [488, 60.368]
|
244
|
+
"insert into keyspace (key, ?) values (?)", [488, 60.368], USE_CQL3
|
220
245
|
).should eq("insert into keyspace (key, 488) values (60.368)")
|
221
246
|
end
|
222
247
|
|
@@ -227,4 +252,4 @@ describe "finish" do
|
|
227
252
|
it "should just return true .. nothing to clean up yet" do
|
228
253
|
Statement.new(nil, 'whatever').finish.should be_true
|
229
254
|
end
|
230
|
-
end
|
255
|
+
end
|