cassandra-cql 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/.gitignore +9 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE.txt +203 -0
  4. data/README.rdoc +78 -0
  5. data/Rakefile +150 -0
  6. data/cassandra-cql.gemspec +29 -0
  7. data/lib/cassandra-cql.rb +39 -0
  8. data/lib/cassandra-cql/database.rb +107 -0
  9. data/lib/cassandra-cql/result.rb +133 -0
  10. data/lib/cassandra-cql/row.rb +59 -0
  11. data/lib/cassandra-cql/schema.rb +108 -0
  12. data/lib/cassandra-cql/statement.rb +111 -0
  13. data/lib/cassandra-cql/types/abstract_type.rb +47 -0
  14. data/lib/cassandra-cql/types/ascii_type.rb +25 -0
  15. data/lib/cassandra-cql/types/boolean_type.rb +25 -0
  16. data/lib/cassandra-cql/types/bytes_type.rb +21 -0
  17. data/lib/cassandra-cql/types/decimal_type.rb +25 -0
  18. data/lib/cassandra-cql/types/double_type.rb +25 -0
  19. data/lib/cassandra-cql/types/float_type.rb +25 -0
  20. data/lib/cassandra-cql/types/integer_type.rb +27 -0
  21. data/lib/cassandra-cql/types/long_type.rb +27 -0
  22. data/lib/cassandra-cql/types/utf8_type.rb +25 -0
  23. data/lib/cassandra-cql/types/uuid_type.rb +27 -0
  24. data/lib/cassandra-cql/utility.rb +37 -0
  25. data/lib/cassandra-cql/uuid.rb +21 -0
  26. data/lib/cassandra-cql/version.rb +19 -0
  27. data/spec/column_family_spec.rb +105 -0
  28. data/spec/comparator_spec.rb +225 -0
  29. data/spec/conf/0.8/cassandra.in.sh +41 -0
  30. data/spec/conf/0.8/cassandra.yaml +61 -0
  31. data/spec/conf/0.8/log4j-server.properties +40 -0
  32. data/spec/conf/0.8/schema.txt +10 -0
  33. data/spec/conf/1.0/cassandra.in.sh +41 -0
  34. data/spec/conf/1.0/cassandra.yaml +416 -0
  35. data/spec/conf/1.0/log4j-server.properties +40 -0
  36. data/spec/conf/1.0/schema.txt +10 -0
  37. data/spec/result_spec.rb +173 -0
  38. data/spec/row_spec.rb +55 -0
  39. data/spec/rowkey_spec.rb +223 -0
  40. data/spec/schema_spec.rb +51 -0
  41. data/spec/spec_helper.rb +23 -0
  42. data/spec/statement_spec.rb +224 -0
  43. data/spec/utility_spec.rb +26 -0
  44. data/spec/uuid_spec.rb +26 -0
  45. data/spec/validation_spec.rb +250 -0
  46. data/vendor/gen-rb/cassandra.rb +2212 -0
  47. data/vendor/gen-rb/cassandra_constants.rb +10 -0
  48. data/vendor/gen-rb/cassandra_types.rb +854 -0
  49. metadata +171 -0
@@ -0,0 +1,39 @@
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
+
17
+ here = File.dirname(__FILE__)
18
+ require "#{here}/../vendor/gen-rb/cassandra"
19
+
20
+ require 'bigdecimal'
21
+ require 'thrift_client'
22
+ require 'cassandra-cql/types/abstract_type'
23
+ require 'cassandra-cql/types/ascii_type'
24
+ require 'cassandra-cql/types/boolean_type'
25
+ require 'cassandra-cql/types/bytes_type'
26
+ require 'cassandra-cql/types/decimal_type'
27
+ require 'cassandra-cql/types/double_type'
28
+ require 'cassandra-cql/types/float_type'
29
+ require 'cassandra-cql/types/integer_type'
30
+ require 'cassandra-cql/types/long_type'
31
+ require 'cassandra-cql/types/utf8_type'
32
+ require 'cassandra-cql/types/uuid_type'
33
+ require 'cassandra-cql/utility'
34
+ require 'cassandra-cql/uuid'
35
+ require 'cassandra-cql/database'
36
+ require 'cassandra-cql/schema'
37
+ require 'cassandra-cql/statement'
38
+ require 'cassandra-cql/result'
39
+ require 'cassandra-cql/row'
@@ -0,0 +1,107 @@
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
+
17
+ module CassandraCQL
18
+ module Error
19
+ class InvalidRequestException < Exception; end
20
+ end
21
+
22
+ class Database
23
+ attr_reader :connection, :schema, :keyspace
24
+
25
+ def initialize(servers, options={}, thrift_client_options={})
26
+ @options = {
27
+ :keyspace => 'system'
28
+ }.merge(options)
29
+
30
+ @thrift_client_options = {
31
+ :exception_class_overrides => CassandraCQL::Thrift::InvalidRequestException
32
+ }.merge(thrift_client_options)
33
+
34
+ @keyspace = @options[:keyspace]
35
+ @servers = servers
36
+ connect!
37
+ execute("USE #{@keyspace}")
38
+ end
39
+
40
+ def connect!
41
+ @connection = ThriftClient.new(CassandraCQL::Thrift::Client, @servers, @thrift_client_options)
42
+ obj = self
43
+ @connection.add_callback(:post_connect) do
44
+ execute("USE #{@keyspace}")
45
+ end
46
+ end
47
+
48
+ def disconnect!
49
+ @connection.disconnect! if active?
50
+ end
51
+
52
+ def active?
53
+ # TODO: This should be replaced with a CQL call that doesn't exist yet
54
+ @connection.describe_version
55
+ true
56
+ rescue Exception
57
+ false
58
+ end
59
+ alias_method :ping, :active?
60
+
61
+ def reset!
62
+ disconnect!
63
+ reconnect!
64
+ end
65
+ alias_method :reconnect!, :reset!
66
+
67
+ def prepare(statement, options={}, &block)
68
+ stmt = Statement.new(self, statement)
69
+ if block_given?
70
+ yield stmt
71
+ else
72
+ stmt
73
+ end
74
+ end
75
+
76
+ def execute(statement, *bind_vars)
77
+ result = Statement.new(self, statement).execute(bind_vars)
78
+ if block_given?
79
+ yield result
80
+ else
81
+ result
82
+ end
83
+ rescue CassandraCQL::Thrift::InvalidRequestException
84
+ raise Error::InvalidRequestException.new($!.why)
85
+ end
86
+
87
+ def execute_cql_query(cql, compression=CassandraCQL::Thrift::Compression::NONE)
88
+ @connection.execute_cql_query(cql, compression)
89
+ rescue CassandraCQL::Thrift::InvalidRequestException
90
+ raise Error::InvalidRequestException.new($!.why)
91
+ end
92
+
93
+ def keyspace=(ks)
94
+ @keyspace = (ks.nil? ? nil : ks.to_s)
95
+ end
96
+
97
+ def keyspaces
98
+ # TODO: This should be replaced with a CQL call that doesn't exist yet
99
+ @connection.describe_keyspaces.map { |keyspace| Schema.new(keyspace) }
100
+ end
101
+
102
+ def schema
103
+ # TODO: This should be replaced with a CQL call that doesn't exist yet
104
+ Schema.new(@connection.describe_keyspace(@keyspace))
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,133 @@
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
+
17
+ module CassandraCQL
18
+ module Error
19
+ class InvalidResultType < Exception; end
20
+ class InvalidCursor < Exception; end
21
+ end
22
+
23
+ class ResultSchema
24
+ attr_reader :names, :values
25
+
26
+ def initialize(schema)
27
+ # When https://issues.apache.org/jira/browse/CASSANDRA-3436 is resolve, no more need to split/last
28
+ @names = Hash.new(schema.default_name_type.split(".").last)
29
+ schema.name_types.each_pair { |key, type|
30
+ @names[key] = type.split(".").last
31
+ }
32
+ @values = Hash.new(schema.default_value_type.split(".").last)
33
+ schema.value_types.each_pair { |key, type|
34
+ @values[key] = type.split(".").last
35
+ }
36
+ end
37
+ end
38
+
39
+ class Result
40
+ attr_reader :result, :schema, :cursor
41
+
42
+ def initialize(result)
43
+ @result = result
44
+ @schema = ResultSchema.new(result.schema) if rows?
45
+ @cursor = 0
46
+ end
47
+
48
+ def void?
49
+ @result.type == CassandraCQL::Thrift::CqlResultType::VOID
50
+ end
51
+
52
+ def int?
53
+ @result.type == CassandraCQL::Thrift::CqlResultType::INT
54
+ end
55
+
56
+ def rows?
57
+ @result.type == CassandraCQL::Thrift::CqlResultType::ROWS
58
+ end
59
+
60
+ def rows
61
+ @result.rows.size
62
+ end
63
+
64
+ def cursor=(cursor)
65
+ @cursor = cursor.to_i
66
+ rescue Exception => e
67
+ raise Error::InvalidCursor, e.to_s
68
+ end
69
+
70
+ def fetch_row
71
+ case @result.type
72
+ when CassandraCQL::Thrift::CqlResultType::ROWS
73
+ return nil if @cursor >= rows
74
+
75
+ row = Row.new(@result.rows[@cursor], @schema)
76
+ @cursor += 1
77
+ return row
78
+ when CassandraCQL::Thrift::CqlResultType::VOID
79
+ return nil
80
+ when CassandraCQL::Thrift::CqlResultType::INT
81
+ return @result.num
82
+ else
83
+ raise Error::InvalidResultType, "Expects one of 0, 1, 2; was #{@result.type} "
84
+ end
85
+ end
86
+
87
+ def fetch
88
+ if block_given?
89
+ while row = fetch_row
90
+ yield row
91
+ end
92
+ else
93
+ fetch_row
94
+ end
95
+ end
96
+
97
+ def fetch_hash
98
+ if block_given?
99
+ while row = fetch_row
100
+ if row.kind_of?(Fixnum)
101
+ yield({row => row})
102
+ else
103
+ yield row.to_hash
104
+ end
105
+ end
106
+ else
107
+ if (row = fetch_row).kind_of?(Fixnum)
108
+ {row => row}
109
+ else
110
+ row.to_hash
111
+ end
112
+ end
113
+ end
114
+
115
+ def fetch_array
116
+ if block_given?
117
+ while row = fetch_row
118
+ if row.kind_of?(Fixnum)
119
+ yield [row]
120
+ else
121
+ yield row.to_a
122
+ end
123
+ end
124
+ else
125
+ if (row = fetch_row).kind_of?(Fixnum)
126
+ [row]
127
+ else
128
+ row.to_a
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,59 @@
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
+
17
+ module CassandraCQL
18
+ class Row
19
+ attr_reader :row
20
+
21
+ def initialize(row, schema)
22
+ @row, @schema = row, schema
23
+ end
24
+
25
+ def [](obj)
26
+ # Rows include the row key so we skip the first one
27
+ column_index = obj.kind_of?(Fixnum) ? obj : column_names.index(obj)
28
+ return nil if column_index.nil?
29
+ column_values[column_index]
30
+ end
31
+
32
+ def column_names
33
+ @names ||= @row.columns.map do |column|
34
+ ColumnFamily.cast(column.name, @schema.names[column.name])
35
+ end
36
+ end
37
+
38
+ def column_values
39
+ @values ||= @row.columns.map { |column| ColumnFamily.cast(column.value, @schema.values[column.name]) }
40
+ end
41
+
42
+ def columns
43
+ @row.columns.size
44
+ end
45
+
46
+ def to_a
47
+ column_values
48
+ end
49
+
50
+ # TODO: This should be an ordered hash
51
+ def to_hash
52
+ Hash[([column_names, column_values]).transpose]
53
+ end
54
+
55
+ def key
56
+ ColumnFamily.cast(@row.key, @schema.values[@row.key])
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,108 @@
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
+
17
+ module CassandraCQL
18
+ class Schema
19
+ attr_reader :schema, :column_families
20
+
21
+ def initialize(schema)
22
+ @schema = schema
23
+ @column_families = {}
24
+ @schema.cf_defs.each { |cf|
25
+ @column_families[cf.name] = ColumnFamily.new(cf)
26
+ }
27
+ end
28
+
29
+ def method_missing(method, *args, &block)
30
+ if @schema.respond_to?(method)
31
+ @schema.send(method)
32
+ else
33
+ super(method, *args, &block)
34
+ end
35
+ end
36
+
37
+ def to_s
38
+ keyspace
39
+ end
40
+
41
+ def keyspace
42
+ name
43
+ end
44
+
45
+ def column_family_names
46
+ @column_families.keys
47
+ end
48
+ alias_method :tables, :column_family_names
49
+ end
50
+
51
+ class ColumnFamily
52
+ attr_reader :cf_def
53
+
54
+ def initialize(cf_def)
55
+ @cf_def = cf_def
56
+ end
57
+
58
+ def method_missing(method, *args, &block)
59
+ if @cf_def.respond_to?(method)
60
+ @cf_def.send(method)
61
+ else
62
+ super(method, *args, &block)
63
+ end
64
+ end
65
+
66
+ def columns
67
+ return @columns if @columns
68
+
69
+ @columns = Hash.new(default_validation_class)
70
+ @cf_def.column_metadata.each do |col|
71
+ @columns[col.name] = col.validation_class
72
+ end
73
+ @columns[key_alias] = key_validation_class
74
+
75
+ @columns
76
+ end
77
+
78
+ def self.cast(value, type)
79
+ return nil if value.nil?
80
+
81
+ if CassandraCQL::Types.const_defined?(type)
82
+ CassandraCQL::Types.const_get(type).cast(value)
83
+ else
84
+ CassandraCQL::Types::AbstractType.cast(value)
85
+ end
86
+ end
87
+
88
+ def name
89
+ @cf_def.name
90
+ end
91
+
92
+ def type
93
+ @cf_def.column_type
94
+ end
95
+
96
+ def id
97
+ @cf_def.id
98
+ end
99
+
100
+ def standard?
101
+ type == 'Standard'
102
+ end
103
+
104
+ def super?
105
+ type == 'Super'
106
+ end
107
+ end
108
+ end