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,111 @@
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 InvalidBindVariable < Exception; end
20
+ class UnescapableObject < Exception; end
21
+ end
22
+
23
+ class Statement
24
+
25
+ KS_CHANGE_RE = /^use (\w+)/i
26
+ KS_DROP_RE = /^drop keyspace (\w+)/i
27
+
28
+ attr_reader :statement
29
+
30
+ def initialize(handle, statement)
31
+ @handle = handle
32
+ prepare(statement)
33
+ end
34
+
35
+ def prepare(statement)
36
+ @statement = statement
37
+ end
38
+
39
+ def execute(bind_vars=[], options={})
40
+ 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))
44
+ end
45
+
46
+ # Change our keyspace if required
47
+ if @statement =~ KS_CHANGE_RE
48
+ @handle.keyspace = $1
49
+ elsif @statement =~ KS_DROP_RE
50
+ @handle.keyspace = nil
51
+ end
52
+
53
+ # We let ints be fetched for now because they'll probably be deprecated later
54
+ if res.void?
55
+ nil
56
+ else
57
+ res
58
+ end
59
+ end
60
+
61
+ def finish
62
+ true
63
+ end
64
+
65
+ def self.escape(obj)
66
+ obj.gsub("'", "''")
67
+ end
68
+
69
+ def self.quote(obj)
70
+ if obj.kind_of?(Array)
71
+ obj.map { |member| quote(member) }.join(",")
72
+ elsif obj.kind_of?(String)
73
+ "'" + obj + "'"
74
+ elsif obj.kind_of?(Fixnum) or obj.kind_of?(Float)
75
+ obj
76
+ else
77
+ raise Error::UnescapableObject, "Unable to escape object of class #{obj.class}"
78
+ end
79
+ end
80
+
81
+ def self.cast_to_cql(obj)
82
+ if obj.kind_of?(Array)
83
+ obj.map { |member| cast_to_cql(member) }
84
+ elsif obj.kind_of?(Fixnum) or obj.kind_of?(Float)
85
+ obj
86
+ elsif obj.kind_of?(Time)
87
+ UUID.new(obj).to_guid
88
+ elsif obj.kind_of?(UUID)
89
+ obj.to_guid
90
+ # There are corner cases where this is an invalid assumption but they are extremely rare.
91
+ # The alternative is to make the user pack the data on their own .. let's not do that until we have to
92
+ elsif obj.kind_of?(String) and Utility.binary_data?(obj)
93
+ escape(obj.unpack('H*')[0])
94
+ else
95
+ RUBY_VERSION >= "1.9" ? escape(obj.to_s.dup.force_encoding('ASCII-8BIT')) : escape(obj.to_s.dup)
96
+ end
97
+ end
98
+
99
+ def self.sanitize(statement, bind_vars=[])
100
+ bind_vars = bind_vars.dup
101
+ expected_bind_vars = statement.count("?")
102
+
103
+ return statement if expected_bind_vars == 0 and bind_vars.empty?
104
+ raise Error::InvalidBindVariable, "Wrong number of bound variables (statement expected #{expected_bind_vars}, was #{bind_vars.size})" if expected_bind_vars != bind_vars.size
105
+
106
+ statement.gsub(/\?/) {
107
+ quote(cast_to_cql(bind_vars.shift))
108
+ }
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,47 @@
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 Types
19
+ class AbstractType
20
+ def self.cast(value)
21
+ value
22
+ end
23
+
24
+ private
25
+
26
+ def self.bytes_to_int(bytes)
27
+ int = 0
28
+ values = bytes.unpack('C*')
29
+ values.each {|v| int = int << 8; int += v; }
30
+ if bytes[0].ord & 128 != 0
31
+ int = int - (1 << bytes.length * 8)
32
+ end
33
+ int
34
+ end
35
+
36
+ def self.bytes_to_long(bytes)
37
+ ints = bytes.unpack("NN")
38
+ val = (ints[0] << 32) + ints[1]
39
+ if val & 2**63 == 2**63
40
+ val - 2**64
41
+ else
42
+ val
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,25 @@
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 Types
19
+ class AsciiType < AbstractType
20
+ def self.cast(value)
21
+ RUBY_VERSION >= "1.9" ? value.to_s.dup.force_encoding('ASCII-8BIT') : value.to_s.dup
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
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 Types
19
+ class BooleanType < AbstractType
20
+ def self.cast(value)
21
+ value.unpack('C') == [1]
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,21 @@
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 Types
19
+ class BytesType < AbstractType; end
20
+ end
21
+ end
@@ -0,0 +1,25 @@
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 Types
19
+ class DecimalType < AbstractType
20
+ def self.cast(value)
21
+ BigDecimal.new(bytes_to_int(value[4..-1]).to_s) * BigDecimal.new('10')**(bytes_to_int(value[0..3])*-1)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
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 Types
19
+ class DoubleType < AbstractType
20
+ def self.cast(value)
21
+ value.unpack('G')[0]
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
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 Types
19
+ class FloatType < AbstractType
20
+ def self.cast(value)
21
+ value.unpack('g')[0]
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,27 @@
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 Types
19
+ class IntegerType < AbstractType
20
+ def self.cast(value)
21
+ bytes_to_int(value)
22
+ end
23
+ end
24
+
25
+ class Int32Type < IntegerType; end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
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 Types
19
+ class LongType < AbstractType
20
+ def self.cast(value)
21
+ bytes_to_long(value)
22
+ end
23
+ end
24
+
25
+ class CounterColumnType < LongType; end
26
+ end
27
+ end
@@ -0,0 +1,25 @@
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 Types
19
+ class UTF8Type < AbstractType
20
+ def self.cast(value)
21
+ RUBY_VERSION >= "1.9" ? value.to_s.dup.force_encoding('UTF-8') : value.to_s.dup
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,27 @@
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 Types
19
+ class UUIDType < AbstractType
20
+ def self.cast(value)
21
+ UUID.new(value)
22
+ end
23
+ end
24
+
25
+ class TimeUUIDType < UUIDType; end
26
+ end
27
+ end
@@ -0,0 +1,37 @@
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
+ require 'zlib'
18
+
19
+ module CassandraCQL
20
+ class Utility
21
+ def self.compress(source, level=2)
22
+ Zlib::Deflate.deflate(source, level)
23
+ end
24
+
25
+ def self.decompress(source)
26
+ Zlib::Inflate.inflate(source)
27
+ end
28
+
29
+ def self.binary_data?(string)
30
+ if RUBY_VERSION >= "1.9"
31
+ string.encoding.name == "ASCII-8BIT"
32
+ else
33
+ string.count("\x00-\x7F", "^ -~\t\r\n").fdiv(string.size) > 0.3 || string.index("\x00") unless string.empty?
34
+ end
35
+ end
36
+ end
37
+ end