cassandra-cql 1.0.2 → 1.0.4

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/Rakefile CHANGED
@@ -6,12 +6,12 @@ require 'rspec/core'
6
6
  require 'rspec/core/rake_task'
7
7
 
8
8
  CassandraBinaries = {
9
- '0.8' => 'http://archive.apache.org/dist/cassandra/0.8.4/apache-cassandra-0.8.4-bin.tar.gz',
10
- '1.0' => 'http://archive.apache.org/dist/cassandra/1.0.1/apache-cassandra-1.0.1-bin.tar.gz',
9
+ '0.8' => 'http://archive.apache.org/dist/cassandra/0.8.8/apache-cassandra-0.8.8-bin.tar.gz',
10
+ '1.0' => 'http://archive.apache.org/dist/cassandra/1.0.5/apache-cassandra-1.0.5-bin.tar.gz',
11
11
  }
12
12
 
13
13
  CASSANDRA_VERSION = ENV['CASSANDRA_VERSION'] || '1.0'
14
- CASSANDRA_HOME = File.dirname(__FILE__) + '/tmp'
14
+ CASSANDRA_HOME = ENV['CASSANDRA_HOME'] || File.dirname(__FILE__) + '/tmp'
15
15
  CASSANDRA_PIDFILE = ENV['CASSANDRA_PIDFILE'] || "#{CASSANDRA_HOME}/cassandra.pid"
16
16
 
17
17
  RSpec::Core::RakeTask.new(:spec) do |spec|
@@ -111,12 +111,12 @@ namespace :cassandra do
111
111
  env = setup_environment
112
112
  sh("kill $(cat #{CASSANDRA_PIDFILE})")
113
113
  end
114
-
114
+
115
115
  desc "Delete all data files in #{CASSANDRA_HOME}"
116
116
  task :clean do
117
117
  sh("rm -rf #{File.join(CASSANDRA_HOME, "cassandra-#{CASSANDRA_VERSION}", 'data')}")
118
118
  end
119
-
119
+
120
120
  end
121
121
 
122
122
  desc "Start Cassandra"
@@ -14,8 +14,13 @@ See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  =end
16
16
 
17
- here = File.dirname(__FILE__)
18
- require "#{here}/../vendor/gen-rb/cassandra"
17
+ module CassandraCQL; end;
18
+ unless CassandraCQL.respond_to?(:CASSANDRA_VERSION)
19
+ require "cassandra-cql/1.0"
20
+ end
21
+
22
+ here = File.expand_path(File.dirname(__FILE__))
23
+ require "#{here}/../vendor/#{CassandraCQL.CASSANDRA_VERSION}/gen-rb/cassandra"
19
24
 
20
25
  require 'bigdecimal'
21
26
  require 'date'
@@ -39,3 +44,6 @@ require 'cassandra-cql/schema'
39
44
  require 'cassandra-cql/statement'
40
45
  require 'cassandra-cql/result'
41
46
  require 'cassandra-cql/row'
47
+
48
+ require "cassandra-cql/#{CassandraCQL.CASSANDRA_VERSION}/result"
49
+ require "cassandra-cql/#{CassandraCQL.CASSANDRA_VERSION}/statement"
@@ -0,0 +1,7 @@
1
+ module CassandraCQL
2
+ def self.CASSANDRA_VERSION
3
+ "0.8"
4
+ end
5
+ end
6
+
7
+ require "#{File.expand_path(File.dirname(__FILE__))}/../cassandra-cql"
@@ -0,0 +1,23 @@
1
+ module CassandraCQL
2
+ module V08
3
+ class ResultSchema < CassandraCQL::ResultSchema
4
+ def initialize(column_family)
5
+ type_slice = lambda {|type| type[type.rindex('.')+1..-1] }
6
+
7
+ @names = Hash.new(type_slice.call(column_family.comparator_type))
8
+ @values = Hash.new(type_slice.call(column_family.default_validation_class))
9
+ column_family.columns.each_pair do |name, type|
10
+ @values[name] = type_slice.call(type)
11
+ end
12
+ end
13
+ end
14
+
15
+ class Result < CassandraCQL::Result
16
+ def initialize(result, column_family)
17
+ @result = result
18
+ @schema = ResultSchema.new(column_family) if rows?
19
+ @cursor = 0
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,38 @@
1
+ module CassandraCQL
2
+ module V08
3
+ class Statement < CassandraCQL::Statement
4
+ SCHEMA_CHANGE_RE = /\s*(create|drop|alter)\s+(\w+)/i
5
+ COLFAM_RE = /\s*select.*from\s+'?(\w+)/i
6
+
7
+ def execute(bind_vars=[], options={})
8
+ column_family = nil
9
+ if @statement =~ COLFAM_RE
10
+ column_family = @handle.schema.column_families[$1].dup
11
+ end
12
+
13
+ sanitized_query = self.class.sanitize(@statement, bind_vars)
14
+ compression_type = CassandraCQL::Thrift::Compression::NONE
15
+ if options[:compression]
16
+ compression_type = CassandraCQL::Thrift::Compression::GZIP
17
+ sanitized_query = Utility.compress(sanitized_query)
18
+ end
19
+
20
+ res = V08::Result.new(@handle.execute_cql_query(sanitized_query, compression_type), column_family)
21
+
22
+ # Change our keyspace if required
23
+ if @statement =~ KS_CHANGE_RE
24
+ @handle.keyspace = $1
25
+ elsif @statement =~ KS_DROP_RE
26
+ @handle.keyspace = nil
27
+ end
28
+
29
+ # We let ints be fetched for now because they'll probably be deprecated later
30
+ if res.void?
31
+ nil
32
+ else
33
+ res
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,7 @@
1
+ module CassandraCQL
2
+ def self.CASSANDRA_VERSION
3
+ "1.0"
4
+ end
5
+ end
6
+
7
+ require "#{File.expand_path(File.dirname(__FILE__))}/../cassandra-cql"
@@ -0,0 +1,6 @@
1
+ module CassandraCQL
2
+ module V10
3
+ class Result < CassandraCQL::Result
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module CassandraCQL
2
+ module V10
3
+ class Statement < CassandraCQL::Statement
4
+ end
5
+ end
6
+ end
@@ -42,6 +42,7 @@ module CassandraCQL
42
42
  obj = self
43
43
  @connection.add_callback(:post_connect) do
44
44
  execute("USE #{@keyspace}")
45
+ @connection.login(@auth_request) if @auth_request
45
46
  end
46
47
  end
47
48
 
@@ -60,12 +61,19 @@ module CassandraCQL
60
61
 
61
62
  def reset!
62
63
  disconnect!
63
- reconnect!
64
+ connect!
64
65
  end
65
66
  alias_method :reconnect!, :reset!
66
67
 
68
+ def statement_class
69
+ return @statement_class if @statement_class
70
+
71
+ version_module = 'V' + CassandraCQL.CASSANDRA_VERSION.gsub('.', '')
72
+ return @statement_class = CassandraCQL.const_get(version_module).const_get(:Statement)
73
+ end
74
+
67
75
  def prepare(statement, options={}, &block)
68
- stmt = Statement.new(self, statement)
76
+ stmt = statement_class.new(self, statement)
69
77
  if block_given?
70
78
  yield stmt
71
79
  else
@@ -74,7 +82,7 @@ module CassandraCQL
74
82
  end
75
83
 
76
84
  def execute(statement, *bind_vars)
77
- result = Statement.new(self, statement).execute(bind_vars)
85
+ result = statement_class.new(self, statement).execute(bind_vars)
78
86
  if block_given?
79
87
  yield result
80
88
  else
@@ -103,5 +111,15 @@ module CassandraCQL
103
111
  # TODO: This should be replaced with a CQL call that doesn't exist yet
104
112
  Schema.new(@connection.describe_keyspace(@keyspace))
105
113
  end
114
+
115
+ def login!(username, password)
116
+ request = CassandraCQL::Thrift::AuthenticationRequest.new
117
+ request.credentials = {'username' => username, 'password' => password}
118
+ ret = @connection.login(request)
119
+ # To avoid a double login on the initial connect, we set
120
+ # @auth_request after the first successful login.
121
+ @auth_request = request
122
+ ret
123
+ end
106
124
  end
107
125
  end
@@ -23,7 +23,6 @@ module CassandraCQL
23
23
  end
24
24
 
25
25
  def [](obj)
26
- # Rows include the row key so we skip the first one
27
26
  column_index = obj.kind_of?(Fixnum) ? obj : column_names.index(obj)
28
27
  return nil if column_index.nil?
29
28
  column_values[column_index]
@@ -51,9 +50,5 @@ module CassandraCQL
51
50
  def to_hash
52
51
  Hash[([column_names, column_values]).transpose]
53
52
  end
54
-
55
- def key
56
- ColumnFamily.cast(@row.key, @schema.values[@row.key])
57
- end
58
53
  end
59
54
  end
@@ -31,18 +31,21 @@ module CassandraCQL
31
31
  @handle = handle
32
32
  prepare(statement)
33
33
  end
34
-
34
+
35
35
  def prepare(statement)
36
36
  @statement = statement
37
37
  end
38
-
38
+
39
39
  def execute(bind_vars=[], options={})
40
+ sanitized_query = self.class.sanitize(@statement, bind_vars)
41
+ compression_type = CassandraCQL::Thrift::Compression::NONE
40
42
  if options[:compression]
41
- res = Result.new(@handle.execute_cql_query(Utility.compress(self.class.sanitize(@statement, bind_vars)), CassandraCQL::Thrift::Compression::GZIP))
42
- else
43
- res = Result.new(@handle.execute_cql_query(self.class.sanitize(@statement, bind_vars), CassandraCQL::Thrift::Compression::NONE))
43
+ compression_type = CassandraCQL::Thrift::Compression::GZIP
44
+ sanitized_query = Utility.compress(sanitized_query)
44
45
  end
45
46
 
47
+ res = Result.new(@handle.execute_cql_query(sanitized_query, compression_type))
48
+
46
49
  # Change our keyspace if required
47
50
  if @statement =~ KS_CHANGE_RE
48
51
  @handle.keyspace = $1
@@ -1,3 +1,19 @@
1
+ =begin
2
+ Copyright 2011 Inside Systems, Inc.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ =end
16
+
1
17
  module CassandraCQL
2
18
  module Types
3
19
  class DateType < AbstractType
@@ -15,5 +15,5 @@ limitations under the License.
15
15
  =end
16
16
 
17
17
  module CassandraCQL
18
- VERSION = "1.0.2"
18
+ VERSION = "1.0.4"
19
19
  end
@@ -97,23 +97,24 @@ describe "Comparator Roundtrip tests" do
97
97
  end
98
98
  res.class.should eq(Time)
99
99
  end
100
-
101
100
  end
102
101
 
103
- context "with decimal comparator" do
104
- let(:cf_name) { "comparator_cf_decimal" }
105
- before(:each) { create_column_family(cf_name, 'DecimalType') }
102
+ if CASSANDRA_VERSION.to_f >= 1.0
103
+ context "with decimal comparator" do
104
+ let(:cf_name) { "comparator_cf_decimal" }
105
+ before(:each) { create_column_family(cf_name, 'DecimalType') }
106
106
 
107
- def test_for_value(value)
108
- create_and_fetch_column(cf_name, value).should eq(value)
109
- create_and_fetch_column(cf_name, value*-1).should eq(value*-1)
110
- end
111
-
112
- it "should return a small decimal" do
113
- test_for_value(15.333)
114
- end
115
- it "should return a huge decimal" do
116
- test_for_value(BigDecimal.new('129182739481237481341234123411.1029348102934810293481039'))
107
+ def test_for_value(value)
108
+ create_and_fetch_column(cf_name, value).should eq(value)
109
+ create_and_fetch_column(cf_name, value*-1).should eq(value*-1)
110
+ end
111
+
112
+ it "should return a small decimal" do
113
+ test_for_value(15.333)
114
+ end
115
+ it "should return a huge decimal" do
116
+ test_for_value(BigDecimal.new('129182739481237481341234123411.1029348102934810293481039'))
117
+ end
117
118
  end
118
119
  end
119
120
 
@@ -151,26 +152,29 @@ describe "Comparator Roundtrip tests" do
151
152
  end
152
153
  end
153
154
 
154
- context "with int comparator" do
155
- let(:cf_name) { "comparator_cf_int" }
156
- before(:each) { create_column_family(cf_name, 'Int32Type') }
155
+ if CASSANDRA_VERSION.to_f >= 1.0
156
+ #Int32Type was added in 1.0 (CASSANDRA-3031)
157
+ context "with int comparator" do
158
+ let(:cf_name) { "comparator_cf_int" }
159
+ before(:each) { create_column_family(cf_name, 'Int32Type') }
157
160
 
158
- def test_for_value(value)
159
- create_and_fetch_column(cf_name, value).should eq(value)
160
- create_and_fetch_column(cf_name, value*-1).should eq(value*-1)
161
- end
162
-
163
- it "should properly convert integer values that fit into 1 byte" do
164
- test_for_value(1)
165
- end
166
- it "should properly convert integer values that fit into 2 bytes" do
167
- test_for_value(2**8 + 80)
168
- end
169
- it "should properly convert integer values that fit into 3 bytes" do
170
- test_for_value(2**16 + 622)
171
- end
172
- it "should properly convert integer values that fit into 4 bytes" do
173
- test_for_value(2**24 + 45820)
161
+ def test_for_value(value)
162
+ create_and_fetch_column(cf_name, value).should eq(value)
163
+ create_and_fetch_column(cf_name, value*-1).should eq(value*-1)
164
+ end
165
+
166
+ it "should properly convert integer values that fit into 1 byte" do
167
+ test_for_value(1)
168
+ end
169
+ it "should properly convert integer values that fit into 2 bytes" do
170
+ test_for_value(2**8 + 80)
171
+ end
172
+ it "should properly convert integer values that fit into 3 bytes" do
173
+ test_for_value(2**16 + 622)
174
+ end
175
+ it "should properly convert integer values that fit into 4 bytes" do
176
+ test_for_value(2**24 + 45820)
177
+ end
174
178
  end
175
179
  end
176
180
 
@@ -0,0 +1,25 @@
1
+ require File.expand_path('spec_helper.rb', File.dirname(__FILE__))
2
+ include CassandraCQL
3
+
4
+ describe "Database" do
5
+ before do
6
+ @connection = setup_cassandra_connection
7
+ end
8
+
9
+ describe "reset!" do
10
+ it "should create a new connection" do
11
+ @connection.should_receive(:connect!)
12
+ @connection.reset!
13
+ end
14
+ end
15
+
16
+ describe "login!" do
17
+ it "should call login! on connection" do
18
+ creds = { 'username' => 'myuser', 'password' => 'mypass' }
19
+ @connection.connection.should_receive(:login) do |auth|
20
+ auth.credentials.should eq(creds)
21
+ end
22
+ @connection.login!(creds['username'], creds['password'])
23
+ end
24
+ end
25
+ end
@@ -34,12 +34,6 @@ describe "basic methods" do
34
34
  end
35
35
  end
36
36
 
37
- context "key" do
38
- it "should return the cql_result row key" do
39
- @row.key.should eq(@row.row.key)
40
- end
41
- end
42
-
43
37
  context "checking casting" do
44
38
  it "should return column_values for to_a" do
45
39
  @row.to_a.should eq(@row.column_values)
@@ -56,7 +56,11 @@ describe "Validation Roundtrip tests" do
56
56
 
57
57
  context "with blob row_key_validation" do
58
58
  let(:cf_name) { "row_key_validation_cf_blob" }
59
- before(:each) { create_column_family(cf_name, 'blob') }
59
+ if CASSANDRA_VERSION.to_f == 0.8
60
+ before(:each) { create_column_family(cf_name, 'bytea') }
61
+ else
62
+ before(:each) { create_column_family(cf_name, 'blob') }
63
+ end
60
64
 
61
65
  it "should return a blob" do
62
66
  bytes = "binary\x00"
@@ -78,20 +82,22 @@ describe "Validation Roundtrip tests" do
78
82
  end
79
83
  end
80
84
 
81
- context "with decimal row_key_validation" do
82
- let(:cf_name) { "row_key_validation_cf_decimal" }
83
- before(:each) { create_column_family(cf_name, 'decimal') }
85
+ if CASSANDRA_VERSION.to_f >= 1.0
86
+ context "with decimal row_key_validation" do
87
+ let(:cf_name) { "row_key_validation_cf_decimal" }
88
+ before(:each) { create_column_family(cf_name, 'decimal') }
84
89
 
85
- def test_for_value(value)
86
- create_and_fetch_column(cf_name, value*-1).should eq(value*-1)
87
- create_and_fetch_column(cf_name, value).should eq(value)
88
- end
89
-
90
- it "should return a small decimal" do
91
- test_for_value(15.333)
92
- end
93
- it "should return a huge decimal" do
94
- test_for_value(BigDecimal.new('129182739481237481341234123411.1029348102934810293481039'))
90
+ def test_for_value(value)
91
+ create_and_fetch_column(cf_name, value*-1).should eq(value*-1)
92
+ create_and_fetch_column(cf_name, value).should eq(value)
93
+ end
94
+
95
+ it "should return a small decimal" do
96
+ test_for_value(15.333)
97
+ end
98
+ it "should return a huge decimal" do
99
+ test_for_value(BigDecimal.new('129182739481237481341234123411.1029348102934810293481039'))
100
+ end
95
101
  end
96
102
  end
97
103
 
@@ -167,7 +173,11 @@ describe "Validation Roundtrip tests" do
167
173
 
168
174
  context "with timestamp row_key_validation" do
169
175
  let(:cf_name) { "row_key_validation_cf_timestamp" }
170
- before(:each) { create_column_family(cf_name, 'timestamp') }
176
+ if CASSANDRA_VERSION.to_f == 0.8
177
+ before(:each) { create_column_family(cf_name, 'date') }
178
+ else
179
+ before(:each) { create_column_family(cf_name, 'timestamp') }
180
+ end
171
181
 
172
182
  it "should return a timestamp" do
173
183
  uuid = UUID.new