cequel 1.5.0 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Appraisals +4 -17
- data/CHANGELOG.md +8 -0
- data/DRIVER_TODO +5 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +110 -65
- data/README.md +4 -3
- data/Rakefile +39 -3
- data/Vagrantfile +10 -13
- data/cequel.gemspec +42 -0
- data/lib/cequel.rb +2 -2
- data/lib/cequel/metal/data_set.rb +1 -1
- data/lib/cequel/metal/keyspace.rb +23 -15
- data/lib/cequel/metal/logging.rb +1 -1
- data/lib/cequel/metal/request_logger.rb +1 -1
- data/lib/cequel/metal/writer.rb +1 -1
- data/lib/cequel/record.rb +1 -1
- data/lib/cequel/record/association_collection.rb +1 -1
- data/lib/cequel/record/associations.rb +1 -1
- data/lib/cequel/record/belongs_to_association.rb +1 -1
- data/lib/cequel/record/collection.rb +34 -28
- data/lib/cequel/record/data_set_builder.rb +1 -1
- data/lib/cequel/record/lazy_record_collection.rb +1 -1
- data/lib/cequel/record/persistence.rb +4 -2
- data/lib/cequel/record/properties.rb +2 -2
- data/lib/cequel/record/record_set.rb +1 -1
- data/lib/cequel/record/schema.rb +2 -2
- data/lib/cequel/record/scoped.rb +1 -1
- data/lib/cequel/schema/create_table_dsl.rb +1 -1
- data/lib/cequel/schema/keyspace.rb +17 -2
- data/lib/cequel/schema/migration_validator.rb +1 -1
- data/lib/cequel/schema/update_table_dsl.rb +1 -1
- data/lib/cequel/type.rb +5 -5
- data/lib/cequel/util.rb +30 -0
- data/lib/cequel/uuids.rb +5 -5
- data/lib/cequel/version.rb +1 -1
- data/spec/examples/metal/keyspace_spec.rb +1 -1
- data/spec/examples/record/list_spec.rb +9 -0
- data/spec/examples/record/persistence_spec.rb +2 -2
- data/spec/examples/schema/keyspace_spec.rb +1 -2
- data/spec/examples/schema/table_reader_spec.rb +1 -1
- data/spec/examples/spec_helper.rb +3 -0
- data/spec/examples/uuids_spec.rb +1 -1
- data/spec/support/helpers.rb +7 -5
- data/tags +836 -0
- metadata +49 -38
data/Vagrantfile
CHANGED
@@ -11,7 +11,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
|
11
11
|
# please see the online documentation at vagrantup.com.
|
12
12
|
|
13
13
|
# Every Vagrant virtual environment requires a box to build off of.
|
14
|
-
config.vm.box = "
|
14
|
+
config.vm.box = "ubuntu/trusty64"
|
15
15
|
|
16
16
|
# The url from where the 'config.vm.box' box will be fetched if it
|
17
17
|
# doesn't already exist on the user's system.
|
@@ -45,13 +45,9 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
|
45
45
|
# backing providers for Vagrant. These expose provider-specific options.
|
46
46
|
# Example for VirtualBox:
|
47
47
|
#
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
#
|
52
|
-
# # Use VBoxManage to customize the VM. For example to change memory:
|
53
|
-
# vb.customize ["modifyvm", :id, "--memory", "1024"]
|
54
|
-
# end
|
48
|
+
config.vm.provider :virtualbox do |vb|
|
49
|
+
vb.memory = 1024
|
50
|
+
end
|
55
51
|
#
|
56
52
|
# View the documentation for the provider you're using for more
|
57
53
|
# information on available options.
|
@@ -131,14 +127,15 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
|
131
127
|
echo "start on runlevel [2345]
|
132
128
|
stop on runlevel [06]
|
133
129
|
exec /opt/apache-cassandra-$1/bin/cassandra" > /etc/init/cassandra.conf
|
134
|
-
sed -i -e 's
|
135
|
-
sed -i -e 's
|
136
|
-
sed -i -e 's
|
130
|
+
sed -i -e 's/.*broadcast_rpc_address:.*/broadcast_rpc_address: 127.0.0.1/' /opt/apache-cassandra-$1/conf/cassandra.yaml
|
131
|
+
sed -i -e 's/^rpc_address:.*/rpc_address: 0.0.0.0/' /opt/apache-cassandra-$1/conf/cassandra.yaml
|
132
|
+
sed -i -e 's/^start_native_transport:.*/start_native_transport: true/' /opt/apache-cassandra-$1/conf/cassandra.yaml
|
133
|
+
sed -i -e 's/^start_rpc:.*/start_rpc: true/' /opt/apache-cassandra-$1/conf/cassandra.yaml
|
137
134
|
service cassandra start
|
138
135
|
SH
|
139
136
|
|
140
|
-
|
141
|
-
|
137
|
+
versions = File.read(File.expand_path('../.cassandra-versions', __FILE__)).each_line
|
138
|
+
.map(&:strip).grep(/^(1\.2\.|2\.)/)
|
142
139
|
versions.each do |version|
|
143
140
|
java_version = version =~ /^1/ ? '6' : '7'
|
144
141
|
config.vm.define version do |machine|
|
data/cequel.gemspec
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.expand_path('../lib/cequel/version', __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'cequel'
|
5
|
+
s.version = Cequel::VERSION
|
6
|
+
s.authors = [
|
7
|
+
'Mat Brown', 'Aubrey Holland', 'Keenan Brock', 'Insoo Buzz Jung',
|
8
|
+
'Louis Simoneau', 'Peter Williams', 'Kenneth Hoffman', 'Antti Tapio',
|
9
|
+
'Ilya Bazylchuk', 'Dan Cardamore', 'Kei Kusakari', 'Oleh Novosad',
|
10
|
+
'John Smart', 'Angelo Lakra', 'Olivier Lance', 'Tomohiro Nishimura',
|
11
|
+
'Masaki Takahashi', 'G Gordon Worley III', 'Clark Bremer', 'Tamara Temple',
|
12
|
+
'Long On', 'Lucas Mundim'
|
13
|
+
]
|
14
|
+
s.homepage = "https://github.com/cequel/cequel"
|
15
|
+
s.email = 'mat.a.brown@gmail.com'
|
16
|
+
s.license = 'MIT'
|
17
|
+
s.summary = 'Full-featured, ActiveModel-compliant ORM for Cassandra using CQL3'
|
18
|
+
s.description = <<DESC
|
19
|
+
Cequel is an ActiveRecord-like domain model layer for Cassandra that exposes
|
20
|
+
the robust data modeling capabilities of CQL3, including parent-child
|
21
|
+
relationships via compound primary keys and in-memory atomic manipulation of
|
22
|
+
collection columns.
|
23
|
+
DESC
|
24
|
+
|
25
|
+
s.files = Dir['lib/**/*.rb', 'templates/**/*', 'spec/**/*.rb', '[A-Z]*']
|
26
|
+
s.test_files = Dir['spec/examples/**/*.rb']
|
27
|
+
s.has_rdoc = true
|
28
|
+
s.extra_rdoc_files = 'README.md'
|
29
|
+
s.required_ruby_version = '>= 1.9'
|
30
|
+
s.add_runtime_dependency 'activemodel', '>= 3.1', '< 5.0'
|
31
|
+
s.add_runtime_dependency 'cassandra-driver', '~> 1.0'
|
32
|
+
s.add_development_dependency 'appraisal', '~> 1.0'
|
33
|
+
s.add_development_dependency 'wwtd', '~> 0.5'
|
34
|
+
s.add_development_dependency 'rake', '~> 10.1'
|
35
|
+
s.add_development_dependency 'rspec', '~> 3.1'
|
36
|
+
s.add_development_dependency 'rspec-its', '~> 1.0'
|
37
|
+
s.add_development_dependency 'rubocop', '~> 0.28'
|
38
|
+
s.add_development_dependency 'timecop', '~> 0.7'
|
39
|
+
s.add_development_dependency 'travis', '~> 1.7'
|
40
|
+
s.add_development_dependency 'yard', '~> 0.6'
|
41
|
+
s.requirements << 'Cassandra >= 1.2.0'
|
42
|
+
end
|
data/lib/cequel.rb
CHANGED
@@ -4,13 +4,13 @@ require 'delegate'
|
|
4
4
|
require 'active_support'
|
5
5
|
require 'active_support/deprecation'
|
6
6
|
require 'active_support/core_ext'
|
7
|
-
require '
|
7
|
+
require 'cassandra'
|
8
8
|
|
9
9
|
require 'cequel/errors'
|
10
|
+
require 'cequel/util'
|
10
11
|
require 'cequel/metal'
|
11
12
|
require 'cequel/schema'
|
12
13
|
require 'cequel/type'
|
13
|
-
require 'cequel/util'
|
14
14
|
require 'cequel/uuids'
|
15
15
|
require 'cequel/instrumentation'
|
16
16
|
require 'cequel/record'
|
@@ -9,7 +9,7 @@ module Cequel
|
|
9
9
|
# instance.
|
10
10
|
#
|
11
11
|
class Keyspace
|
12
|
-
extend Forwardable
|
12
|
+
extend Util::Forwardable
|
13
13
|
include Logging
|
14
14
|
include MonitorMixin
|
15
15
|
|
@@ -154,9 +154,7 @@ module Cequel
|
|
154
154
|
#
|
155
155
|
def client
|
156
156
|
synchronize do
|
157
|
-
@client ||=
|
158
|
-
client.use(name) if name
|
159
|
-
end
|
157
|
+
@client ||= cluster.connect(name)
|
160
158
|
end
|
161
159
|
end
|
162
160
|
|
@@ -193,8 +191,9 @@ module Cequel
|
|
193
191
|
log('CQL', statement, *bind_vars) do
|
194
192
|
begin
|
195
193
|
client.execute(sanitize(statement, bind_vars),
|
196
|
-
consistency || default_consistency)
|
197
|
-
rescue
|
194
|
+
consistency: consistency || default_consistency)
|
195
|
+
rescue Cassandra::Errors::NoHostsAvailable,
|
196
|
+
Ione::Io::ConnectionError => e
|
198
197
|
clear_active_connections!
|
199
198
|
raise if retries == 0
|
200
199
|
retries -= 1
|
@@ -213,8 +212,11 @@ module Cequel
|
|
213
212
|
if defined? @client
|
214
213
|
remove_instance_variable(:@client)
|
215
214
|
end
|
216
|
-
if defined? @
|
217
|
-
remove_instance_variable(:@
|
215
|
+
if defined? @client_without_keyspace
|
216
|
+
remove_instance_variable(:@client_without_keyspace)
|
217
|
+
end
|
218
|
+
if defined? @cluster
|
219
|
+
remove_instance_variable(:@cluster)
|
218
220
|
end
|
219
221
|
end
|
220
222
|
|
@@ -235,7 +237,7 @@ module Cequel
|
|
235
237
|
CQL
|
236
238
|
|
237
239
|
log('CQL', statement, [name]) do
|
238
|
-
|
240
|
+
client_without_keyspace.execute(sanitize(statement, [name])).any?
|
239
241
|
end
|
240
242
|
end
|
241
243
|
|
@@ -249,15 +251,21 @@ module Cequel
|
|
249
251
|
def_delegator :lock, :synchronize
|
250
252
|
private :lock
|
251
253
|
|
252
|
-
def
|
254
|
+
def cluster
|
253
255
|
synchronize do
|
254
|
-
@
|
256
|
+
@cluster ||= Cassandra.cluster(client_options)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def client_without_keyspace
|
261
|
+
synchronize do
|
262
|
+
@client_without_keyspace ||= cluster.connect
|
255
263
|
end
|
256
264
|
end
|
257
265
|
|
258
266
|
def client_options
|
259
267
|
{hosts: hosts, port: port}.tap do |options|
|
260
|
-
options
|
268
|
+
options.merge!(credentials) if credentials
|
261
269
|
end
|
262
270
|
end
|
263
271
|
|
@@ -272,9 +280,9 @@ module Cequel
|
|
272
280
|
def extract_hosts_and_port(configuration)
|
273
281
|
hosts, ports = [], Set[]
|
274
282
|
ports << configuration[:port] if configuration.key?(:port)
|
275
|
-
|
276
|
-
:host, configuration.fetch(:hosts, '127.0.0.1'))
|
277
|
-
|
283
|
+
host_or_hosts =
|
284
|
+
configuration.fetch(:host, configuration.fetch(:hosts, '127.0.0.1'))
|
285
|
+
Array.wrap(host_or_hosts).each do |host_port|
|
278
286
|
host, port = host_port.split(':')
|
279
287
|
hosts << host
|
280
288
|
if port
|
data/lib/cequel/metal/logging.rb
CHANGED
data/lib/cequel/metal/writer.rb
CHANGED
data/lib/cequel/record.rb
CHANGED
@@ -53,7 +53,7 @@ module Cequel
|
|
53
53
|
#
|
54
54
|
module Collection
|
55
55
|
extend ActiveSupport::Concern
|
56
|
-
extend Forwardable
|
56
|
+
extend Util::Forwardable
|
57
57
|
|
58
58
|
#
|
59
59
|
# @!method loaded?
|
@@ -137,12 +137,16 @@ module Cequel
|
|
137
137
|
def to_modify(&block)
|
138
138
|
if loaded?
|
139
139
|
model.__send__("#{column_name}_will_change!")
|
140
|
-
block.call
|
140
|
+
block.call
|
141
141
|
else modifications << block
|
142
142
|
end
|
143
143
|
self
|
144
144
|
end
|
145
145
|
|
146
|
+
def to_update
|
147
|
+
yield unless model.new_record?
|
148
|
+
end
|
149
|
+
|
146
150
|
def modifications
|
147
151
|
@modifications ||= []
|
148
152
|
end
|
@@ -231,15 +235,17 @@ module Cequel
|
|
231
235
|
"indices"
|
232
236
|
end
|
233
237
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
238
|
+
to_update do
|
239
|
+
if count.nil?
|
240
|
+
updater.list_replace(column_name, first, element)
|
241
|
+
else
|
242
|
+
element = Array.wrap(element)
|
243
|
+
count.times do |i|
|
244
|
+
if i < element.length
|
245
|
+
updater.list_replace(column_name, first+i, element[i])
|
246
|
+
else
|
247
|
+
deleter.list_remove_at(column_name, first+i)
|
248
|
+
end
|
243
249
|
end
|
244
250
|
end
|
245
251
|
end
|
@@ -253,7 +259,7 @@ module Cequel
|
|
253
259
|
# @return [List] self
|
254
260
|
#
|
255
261
|
def clear
|
256
|
-
deleter.delete_columns(column_name)
|
262
|
+
to_update { deleter.delete_columns(column_name) }
|
257
263
|
to_modify { super }
|
258
264
|
end
|
259
265
|
|
@@ -265,7 +271,7 @@ module Cequel
|
|
265
271
|
#
|
266
272
|
def concat(array)
|
267
273
|
array = cast_collection(array)
|
268
|
-
updater.list_append(column_name, array)
|
274
|
+
to_update { updater.list_append(column_name, array) }
|
269
275
|
to_modify { super }
|
270
276
|
end
|
271
277
|
|
@@ -277,7 +283,7 @@ module Cequel
|
|
277
283
|
#
|
278
284
|
def delete(object)
|
279
285
|
object = cast_element(object)
|
280
|
-
updater.list_remove(column_name, object)
|
286
|
+
to_update { updater.list_remove(column_name, object) }
|
281
287
|
to_modify { super }
|
282
288
|
end
|
283
289
|
|
@@ -288,7 +294,7 @@ module Cequel
|
|
288
294
|
# @return [List] self
|
289
295
|
#
|
290
296
|
def delete_at(index)
|
291
|
-
deleter.list_remove_at(column_name, index)
|
297
|
+
to_update { deleter.list_remove_at(column_name, index) }
|
292
298
|
to_modify { super }
|
293
299
|
end
|
294
300
|
|
@@ -300,7 +306,7 @@ module Cequel
|
|
300
306
|
#
|
301
307
|
def push(*objects)
|
302
308
|
objects.map! { |object| cast_element(object) }
|
303
|
-
updater.list_append(column_name, objects)
|
309
|
+
to_update { updater.list_append(column_name, objects) }
|
304
310
|
to_modify { super }
|
305
311
|
end
|
306
312
|
alias_method :<<, :push
|
@@ -314,7 +320,7 @@ module Cequel
|
|
314
320
|
#
|
315
321
|
def replace(array)
|
316
322
|
array = cast_collection(array)
|
317
|
-
updater.set(column_name => array)
|
323
|
+
to_update { updater.set(column_name => array) }
|
318
324
|
to_modify { super }
|
319
325
|
end
|
320
326
|
|
@@ -326,7 +332,7 @@ module Cequel
|
|
326
332
|
#
|
327
333
|
def unshift(*objects)
|
328
334
|
objects.map!(&method(:cast_element))
|
329
|
-
updater.list_prepend(column_name, objects.reverse)
|
335
|
+
to_update { updater.list_prepend(column_name, objects.reverse) }
|
330
336
|
to_modify { super }
|
331
337
|
end
|
332
338
|
alias_method :prepend, :unshift
|
@@ -368,7 +374,7 @@ module Cequel
|
|
368
374
|
#
|
369
375
|
def add(object)
|
370
376
|
object = cast_element(object)
|
371
|
-
updater.set_add(column_name, object)
|
377
|
+
to_update { updater.set_add(column_name, object) }
|
372
378
|
to_modify { super }
|
373
379
|
end
|
374
380
|
alias_method :<<, :add
|
@@ -380,7 +386,7 @@ module Cequel
|
|
380
386
|
# @return [Set] self
|
381
387
|
#
|
382
388
|
def clear
|
383
|
-
deleter.delete_columns(column_name)
|
389
|
+
to_update { deleter.delete_columns(column_name) }
|
384
390
|
to_modify { super }
|
385
391
|
end
|
386
392
|
|
@@ -392,7 +398,7 @@ module Cequel
|
|
392
398
|
#
|
393
399
|
def delete(object)
|
394
400
|
object = cast_element(object)
|
395
|
-
updater.set_remove(column_name, object)
|
401
|
+
to_update { updater.set_remove(column_name, object) }
|
396
402
|
to_modify { super }
|
397
403
|
end
|
398
404
|
|
@@ -404,7 +410,7 @@ module Cequel
|
|
404
410
|
#
|
405
411
|
def replace(set)
|
406
412
|
set = cast_collection(set)
|
407
|
-
updater.set(column_name => set)
|
413
|
+
to_update { updater.set(column_name => set) }
|
408
414
|
to_modify { super }
|
409
415
|
end
|
410
416
|
end
|
@@ -419,7 +425,7 @@ module Cequel
|
|
419
425
|
#
|
420
426
|
class Map < DelegateClass(::Hash)
|
421
427
|
include Collection
|
422
|
-
extend Forwardable
|
428
|
+
extend Util::Forwardable
|
423
429
|
|
424
430
|
# These methods involve mutation that cannot be expressed as a CQL
|
425
431
|
# operation, so are not implemented.
|
@@ -456,7 +462,7 @@ module Cequel
|
|
456
462
|
#
|
457
463
|
def []=(key, value)
|
458
464
|
key = cast_key(key)
|
459
|
-
updater.map_update(column_name, key => value)
|
465
|
+
to_update { updater.map_update(column_name, key => value) }
|
460
466
|
to_modify { super }
|
461
467
|
end
|
462
468
|
alias_method :store, :[]=
|
@@ -468,7 +474,7 @@ module Cequel
|
|
468
474
|
# @return [Map] self
|
469
475
|
#
|
470
476
|
def clear
|
471
|
-
deleter.delete_columns(column_name)
|
477
|
+
to_update { deleter.delete_columns(column_name) }
|
472
478
|
to_modify { super }
|
473
479
|
end
|
474
480
|
|
@@ -480,7 +486,7 @@ module Cequel
|
|
480
486
|
#
|
481
487
|
def delete(key)
|
482
488
|
key = cast_key(key)
|
483
|
-
deleter.map_remove(column_name, key)
|
489
|
+
to_update { deleter.map_remove(column_name, key) }
|
484
490
|
to_modify { super }
|
485
491
|
end
|
486
492
|
|
@@ -492,7 +498,7 @@ module Cequel
|
|
492
498
|
#
|
493
499
|
def merge!(hash)
|
494
500
|
hash = cast_collection(hash)
|
495
|
-
updater.map_update(column_name, hash)
|
501
|
+
to_update { updater.map_update(column_name, hash) }
|
496
502
|
to_modify { super }
|
497
503
|
end
|
498
504
|
alias_method :update, :merge!
|
@@ -505,7 +511,7 @@ module Cequel
|
|
505
511
|
#
|
506
512
|
def replace(hash)
|
507
513
|
hash = cast_collection(hash)
|
508
|
-
updater.set(column_name => hash)
|
514
|
+
to_update { updater.set(column_name => hash) }
|
509
515
|
to_modify { super }
|
510
516
|
end
|
511
517
|
|