cassie 1.0.0.beta.21 → 1.0.0.beta.22

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 44bcb0d0fb09b42a535b4e22a6bbc2b54a92af9a
4
- data.tar.gz: 20a5acd5604630f500c9b06ba15804be0e9acf54
3
+ metadata.gz: 535c984598050fbd5ac382820afbc887b1fd57f5
4
+ data.tar.gz: 7f1a97fc63a2a53b4947c5f2e0ef43bcdfb594a2
5
5
  SHA512:
6
- metadata.gz: 18b4e938a675a39a79e63c1dcc6477941a26ac880c077cb4254533f358ceda7acbeff1df015b123652e87c4a1ca19c02d13c7e461dd9acc7e48c5b7b6f64bc17
7
- data.tar.gz: 1dcd53f870f9ff37b0878922021648e9b8973b1126f7142dadd4a957fb22f5f9d4c74bd74035d7965958d60c42b623b27d0ce47fb3bf522b9aa50c76e8169795
6
+ metadata.gz: e627d882bdd46544ccd753fd5b215c6fbb02d913311e3e982b3e4451039b209420d030fcd2fbd0de08bf1dd8da56a56edc74f7b867318381c1296fd392f87df9
7
+ data.tar.gz: 7f3eed69154aad5ed58fb1463274977462335deaa605fdec9afda5a223f7b213072ac8f1faf76a17a545e5a0539bab46325604fe9155faa0402dc9bf1afa061c
@@ -96,11 +96,11 @@ Cassie provides 3 base classes for these 3 kinds of queries. Subclass `Cassie::D
96
96
  * Adds DSL for `insert_into`, `update`, and `delete_from` statement types
97
97
  * Adds support for automatically mapping values for assignments from a domain object
98
98
 
99
- ##### `Query`
99
+ ##### `Cassie::Query`
100
100
  Includes core functionality for prepared statement execution.
101
101
 
102
102
  * Adds DSL for `select_from` statement type
103
- * Adds `fetch` and `fetch_first` methods for executing and getting results in combination
103
+ * Adds `fetch` and `fetch_first` methods for executing and getting results with a single method call
104
104
  * Adds support for deserializing domain objects from Cassandra rows
105
105
  * Adds support for paging through results with cursors
106
106
  * Adds support for fetching large data sets in memory-efficient batches
@@ -119,7 +119,7 @@ Defining a CQL relation (the `where`) in a cassie query class creates a setter a
119
119
  ```ruby
120
120
  query.user_id = 123
121
121
  query.fetch
122
- => [#<Struct user_id=123, id="some post id">]
122
+ #=> [#<Struct user_id=123, id="some post id">]
123
123
  ```
124
124
 
125
125
  <pre><b>
@@ -141,7 +141,7 @@ end
141
141
  ```ruby
142
142
  query.author = User.new(id: 123)
143
143
  query.fetch
144
- => [#<Struct user_id=123, id="some post id">]
144
+ #=> [#<Struct user_id=123, id="some post id">]
145
145
  ```
146
146
 
147
147
  <pre><b>
@@ -159,7 +159,7 @@ where :user_id, :eq, value: :author_id
159
159
  ```ruby
160
160
  query.author_id = 123
161
161
  query.fetch
162
- => [#<Struct user_id=123, id="some post id">]
162
+ #=> [#<Struct user_id=123, id="some post id">]
163
163
  ```
164
164
 
165
165
  <pre><b>
@@ -181,43 +181,6 @@ Relations can be conditionally evaluated:
181
181
  This can be overdone; it's recommended that one query class be in charge of one kind of query. Avoid query classes that can do too much!
182
182
 
183
183
 
184
- #### Column Selection (`select`)
185
-
186
- ```ruby
187
- select_from :posts_by_author do |t|
188
- t.select :post_id
189
- t.select writetime(:post_id)
190
- end
191
- ```
192
- which is the same as
193
- ```ruby
194
- select_from :posts_by_author
195
-
196
- select :post_id
197
- select writetime(:post_id)
198
- ```
199
-
200
- `count`, `write_time` (also aliased as `writetime`), and `ttl` selector helpers are available.
201
-
202
- ```ruby
203
- select_from :posts_by_author
204
-
205
- select count
206
- ```
207
- ```
208
- => SELECT COUNT(*) FROM posts_by_author;
209
- ```
210
- ```ruby
211
- select_from :posts_by_author
212
-
213
- select :id
214
- select ttl(:popular)
215
- select writetime(:popular), as: :created_at
216
- ```
217
- ```
218
- => SELECT id, TTL(popular), WRITETIME(popular) AS created_at FROM posts_by_author;
219
- ```
220
-
221
184
  #### Values and Assignments (`set`)
222
185
 
223
186
  Set values (for inserts) and assignments (for updates) with the same `set` method. Similar to relations defined with `where`, assignments provide simple getters and setters.
@@ -246,7 +209,7 @@ end
246
209
  query = UpdateUserQuery.new(id: current_user.id)
247
210
  query.username = 'eprothro'
248
211
  query.execute
249
- => true
212
+ #=> true
250
213
  ```
251
214
 
252
215
  Mapping assignemtnt values from a domain object is supported.
@@ -270,7 +233,7 @@ This allows a domain object to be set for the modification object and have assig
270
233
 
271
234
  ```ruby
272
235
  user
273
- => #<User:0x007ff8895ce660 @id=6539, @phone="+15555555555", @email="etp@example.com", @address=nil, @username= "etp">
236
+ #=> #<User:0x007ff8895ce660 @id=6539, @phone="+15555555555", @email="etp@example.com", @address=nil, @username= "etp">
274
237
  UpdateUserQuery.new(user: user).execute
275
238
  ```
276
239
 
@@ -300,7 +263,7 @@ class UpdateUserQuery < Cassandra::Modification
300
263
  ```
301
264
  ```ruby
302
265
  user
303
- => #<User:0x007ff8895ce660 @id=6539, @phone="+15555555555", @email="etp@example.com", @address=nil, @username= "ETP">
266
+ #=> #<User:0x007ff8895ce660 @id=6539, @phone="+15555555555", @email="etp@example.com", @address=nil, @username= "ETP">
304
267
  UpdateUserQuery.new(user: user).execute
305
268
  ```
306
269
 
@@ -336,20 +299,79 @@ end
336
299
 
337
300
  > Note: The `term` option should be used with care. Using it innapropriately could result in inefficient use of prepared statements, and/or leave you potentially vulnerable to injection attacks.
338
301
 
302
+
303
+ #### Column Selection (`select`)
304
+
305
+ By default, all columns will be selected (e.g. '*'). Specify a column for selection with `select`.
306
+
307
+ ```ruby
308
+ select_from :posts_by_author do |t|
309
+ t.select :post_id
310
+ t.select writetime(:post_id)
311
+ end
312
+ ```
313
+ which is the same as
314
+ ```ruby
315
+ select_from :posts_by_author
316
+
317
+ select :post_id
318
+ select writetime(:post_id)
319
+ ```
320
+
321
+ `count`, `write_time` (also aliased as `writetime`), and `ttl` selector helpers are available.
322
+
323
+ ```ruby
324
+ select_from :posts_by_author
325
+
326
+ select count
327
+ ```
328
+ ```
329
+ #=> SELECT COUNT(*) FROM posts_by_author;
330
+ ```
331
+
332
+ Aliasing is supported with the `as` option.
333
+ ```ruby
334
+ select_from :posts_by_author
335
+
336
+ select :id
337
+ select ttl(:popular)
338
+ select writetime(:popular), as: :created_at
339
+ ```
340
+ ```
341
+ #=> SELECT id, TTL(popular), WRITETIME(popular) AS created_at FROM posts_by_author;
342
+ ```
343
+ Arbitrary strings are supported as well in case the DSL gets in the way.
344
+
345
+ ```ruby
346
+ select_from :posts_by_author
347
+
348
+ select 'cowboy, coder'
349
+ ```
350
+ ```
351
+ #=> SELECT cowboy, coder FROM posts_by_author;
352
+ ```
353
+
339
354
  #### Consistency configuration
340
355
 
341
356
  The [consistency level](http://datastax.github.io/ruby-driver/v2.1.6/api/cassandra/#consistencies-constant) for a query is determined by your `Cassie::configuration` by default, falling to back to the `Cassandra` default if none is given.
342
357
 
343
358
  ```ruby
344
359
  Cassie.configuration[:consistency]
345
- => nil
360
+ #=> nil
346
361
 
347
362
  Cassie.cluster.instance_variable_get(:@execution_options).consistency
348
- => :one
363
+ #=> :one
349
364
  ```
350
365
 
351
- Cassie queries allow for a consistency level defined on the object, subclass, then base class levels. If one is found, it will override the `Cassandra` default when the query is executed.
366
+ Cassie queries allow for a consistency level to be defined on the object, subclass, base class, and global levels. If none is found, it will default to the `cluster` default when the query is executed.
352
367
 
368
+ Object writer:
369
+ ```ruby
370
+ query = MyQuery.new
371
+ query.consistency = :all
372
+ query.execute
373
+ ```
374
+ Override Object reader:
353
375
  ```ruby
354
376
  select_from :posts_by_author_category
355
377
 
@@ -370,6 +392,7 @@ Cassie queries allow for a consistency level defined on the object, subclass, th
370
392
  end
371
393
  ```
372
394
 
395
+ Class writer
373
396
  ```ruby
374
397
  select_from :posts_by_author_category
375
398
 
@@ -379,45 +402,85 @@ Cassie queries allow for a consistency level defined on the object, subclass, th
379
402
  consistency :quorum
380
403
  ```
381
404
 
405
+ Cassie query classes
382
406
  ```ruby
383
407
  # lib/tasks/interesting_task.rake
384
408
  require_relative "interesting_worker"
385
409
 
386
410
  task :interesting_task do
387
- Cassandra::Query.consistency = :all
411
+ Cassie::Modification.consistency = :all
388
412
 
389
413
  InterestingWorker.new.perform
390
414
  end
391
415
  ```
392
416
 
417
+ Cassie global default
418
+ ```ruby
419
+ # lib/tasks/interesting_task.rake
420
+ require_relative "interesting_worker"
421
+
422
+ task :interesting_task do
423
+ Cassie::Statements.default_consistency = :all
424
+
425
+ InterestingWorker.new.perform
426
+ end
427
+ ```
428
+
429
+ #### Execution and Result
430
+
431
+ Executing a `Cassie::Query` populates the `result` attribute.
432
+
433
+ ```ruby
434
+ query.execute
435
+ # => true
436
+ query.result.class
437
+ # => Cassie::Statements::Results::QueryResult
438
+ ```
439
+
440
+ The result lazily enumerates domain objects
441
+ ```ruby
442
+ query.execute
443
+ #=> true
444
+ query.result.each
445
+ #=> #<[#< Struct id=:123, username=:eprothro >]>
446
+ ```
447
+
448
+ The result also delegates to the `Cassandra::Result`.
449
+ ```ruby
450
+ query.result.execution_info
451
+ #=> #<Cassandra::Execution::Info:0x007fb404b51390 @payload=nil, @warnings=nil, @keyspace="cassie_test", @statement=#<Cassandra::Statements::Bound:0x3fda0258dee8 @cql="SELECT * FROM users_by_username LIMIT 500;" @params=[]>, @options=#<Cassandra::Execution::Options:0x007fb404b1b880 @consistency=:local_one, @page_size=10000, @trace=false, @timeout=12, @serial_consistency=nil, @arguments=[], @type_hints=[], @paging_state=nil, @idempotent=false, @payload=nil>, @hosts=[#<Cassandra::Host:0x3fda02541390 @ip=127.0.0.1>], @consistency=:local_one, @retries=0, @trace=nil>
452
+ query.result.rows
453
+ #=> #<Enumerator: [{"id"=>123, "username"=>"eprothro"}]>
454
+ ```
455
+
393
456
  #### Finders
394
457
 
395
458
  To avoid confusion with ruby `Enumerable#find` and Rails' specific `find` functionality, Cassie::Query opts to use `fetch` and explict `fetch_first` or `fetch_first!` methods.
396
459
 
397
460
  ##### `fetch`
398
461
 
399
- Executes the query; returns an enumeration of results.
462
+ Calls setters for any opts passed, executes the query, and returns the result.
400
463
 
401
- ```
464
+ ```ruby
402
465
  UsersByResourceQuery.new.fetch(resource: some_resource).to_a
403
- => [#<User id=:123, username=:eprothro>, #<User id=:456, username=:tenderlove>]
466
+ #=> [#<User id=:123, username=:eprothro>, #<User id=:456, username=:tenderlove>]
404
467
  ```
405
468
 
406
469
  ##### `fetch_first` and `fetch_first!`
407
470
 
408
- Executes the query, temporarily limited to 1 result; returns a single result. Bang version raises if no result is found.
471
+ Temporarily limits the query to 1 result; returns a single domain object. Bang version raises if no row is found.
409
472
 
410
- ```
411
- UsersByUsernameQuery.new.fetch_first(username: "eprothro").username
412
- => "eprothro"
473
+ ```ruby
474
+ UsersByUsernameQuery.new.fetch_first(username: "eprothro")
475
+ #=> #<User id=:123, username=:eprothro>
413
476
  ```
414
477
 
415
- ```
478
+ ```ruby
416
479
  UsersByUsernameQuery.new.fetch_first(username: "ActiveRecord")
417
- => nil
480
+ #=> nil
418
481
  ```
419
482
 
420
- ```
483
+ ```ruby
421
484
  UsersByUsernameQuery.new.fetch_first!(username: "active record").username
422
485
  Cassie::Statements::RecordNotFound: CQL row does not exist
423
486
  ```
@@ -428,19 +491,19 @@ Similar to [Rails BatchedFetching](http://guides.rubyonrails.org/v4.2/active_rec
428
491
 
429
492
  ###### `fetch_each`
430
493
 
431
- ```
494
+ ```ruby
432
495
  UsersQuery.new.fetch_each do |user|
433
496
  # only 1000 queried and loaded at a time
434
497
  end
435
498
  ```
436
499
 
437
- ```
500
+ ```ruby
438
501
  UsersQuery.new.fetch_each(batch_size: 500) do |user|
439
502
  # only 500 queried and loaded at a time
440
503
  end
441
504
  ```
442
505
 
443
- ```
506
+ ```ruby
444
507
  UsersQuery.new.fetch_each.with_index do |user, index|
445
508
  # Enumerator chaining without a block
446
509
  end
@@ -448,19 +511,19 @@ end
448
511
 
449
512
  ###### `fetch_in_batches`
450
513
 
451
- ```
514
+ ```ruby
452
515
  UsersQuery.new.fetch_in_batches do |users_array|
453
516
  # only 1000 queried and at a time
454
517
  end
455
518
  ```
456
519
 
457
- ```
520
+ ```ruby
458
521
  UsersQuery.new.fetch_in_batches(batch_size: 500) do |users_array|
459
522
  # only 500 queried and at a time
460
523
  end
461
524
  ```
462
525
 
463
- ```
526
+ ```ruby
464
527
  UsersQuery.new.fetch_in_batches.with_index do |group, index|
465
528
  # Enumerator chaining without a block
466
529
  end
@@ -468,19 +531,19 @@ end
468
531
 
469
532
  #### Deserialization
470
533
 
471
- For Selection Queries, records are deserialized as anonymous structs by default. Each field returned from the database will have an accessor.
534
+ For `Cassie::Query` classes, records are deserialized as anonymous structs by default. Each field returned from the database will have an accessor.
472
535
 
473
536
  ```ruby
474
537
  UsersByUsernameQuery.new.fetch(username: "eprothro")
475
538
  #=> [#<Struct id=:123, username=:eprothro>]
476
539
 
477
- UsersByUsernameQuery.new.fetch_first(username: "eprothro").username
478
- => "eprothro"
540
+ UsersByUsernameQuery.new.fetch_first!(username: "eprothro").username
541
+ #=> "eprothro"
479
542
  ```
480
543
 
481
544
  Most applications will want to override `build_result` to construct more useful domain objects
482
545
 
483
- ```
546
+ ```ruby
484
547
  class UsersByUsernameQuery < Cassie::Query
485
548
 
486
549
  select_from :users_by_username
@@ -495,10 +558,10 @@ end
495
558
 
496
559
  ```ruby
497
560
  UsersByUsernameQuery.new.fetch_first(username: "eprothro")
498
- => #<User:0x007fedec219cd8 @id=123, @username="eprothro">
561
+ #=> #<User:0x007fedec219cd8 @id=123, @username="eprothro">
499
562
  ```
500
563
 
501
- `build_results` may be overridden as well to define completely custom processing of the rows that come back from Cassandra.
564
+ `build_results` may be overridden as well to define custom definition of the enumeration of rows returned from Cassandra.
502
565
 
503
566
  #### Cursored paging
504
567
 
@@ -614,14 +677,14 @@ class RecordsByOwnerQuery < Cassie::Query
614
677
  end
615
678
  end
616
679
  ```
617
- ```
680
+ ```ruby
618
681
  RecordsByOwnerQuery.new(owner: owner, min_record: 99,990).fetch.map(&:record)
619
682
  (2.9ms) SELECT * FROM records_by_owner WHERE owner_id = ? AND bucket = ? AND record >= ? LIMIT 100; [123, 0, 99990]
620
683
  (2.9ms) SELECT * FROM records_by_owner WHERE owner_id = ? AND bucket = ? AND record >= ? LIMIT 100; [123, 1, 99990]
621
- => [99990, 99991, ..., 100089, 100090]
684
+ #=> [99990, 99991, ..., 100089, 100090]
622
685
  ```
623
686
 
624
- The first partition queried is defined within the query class (bucket 0). The linking policy handles recognizing the end of the first partition has been reached, issuing the second query that switches to the second partition (bucket 1), and combining the results from both queries.
687
+ The first partition queried is defined within the query class (bucket 0). The linking policy handles recognizing the end of the first partition has been reached, issuing the second query for the second partition (bucket 1), and combining the results from both queries.
625
688
 
626
689
  By default, this works for ascending and descending orderings when paging in the same order as the clustering order; it also works with cursoring.
627
690
 
@@ -629,9 +692,9 @@ Custom policies can be defined by setting `Query.partition_linker` for more comp
629
692
 
630
693
  #### Prepared statements
631
694
 
632
- A `Cassie::Query` will use prepared statements by default, cacheing prepared statements across all Cassie::Query objects, keyed by the bound CQL string.
695
+ A `Cassie::Query` will use prepared statements by default, cacheing prepared statements across all `Query`, `Modification`, and `Definition` objects, keyed by the unbound CQL string.
633
696
 
634
- To not use prepared statements for a particular query, disable the `.prepare` class option.
697
+ To disable prepared statements for a particular query, disable the `.prepare` class option.
635
698
 
636
699
  ```ruby
637
700
  class MySpecialQuery < Cassie::Query
@@ -657,9 +720,9 @@ set_1 = query.fetch([1, 2, 3])
657
720
  set_2 = query.fetch([7, 8, 9, 10, 11, 12])
658
721
  ```
659
722
 
660
- #### Unbound statements
723
+ #### Non-positional (unbound) statements
661
724
 
662
- Cassie Query features are built around bound statements. However, overriding `#statement`, returning something that a `Cassandra::Session` can execute an unbound statement.
725
+ Cassie Query features are built around using bound statements with positional arguments. However, overriding `#statement`, returning something that a `Cassandra::Session` can execute, will result in an unbound, unprepared statement.
663
726
 
664
727
  ```ruby
665
728
  class MySafeQuery < Cassie::Definition
@@ -669,7 +732,7 @@ class MySafeQuery < Cassie::Definition
669
732
  end
670
733
  ```
671
734
 
672
- > Note: unbound queries may be vulnerable to injection attacks.
735
+ > Note: unbound queries can be vulnerable to injection attacks. Be careful.
673
736
 
674
737
  #### Logging
675
738
 
@@ -1,5 +1,14 @@
1
- module Cassie::Statements::Execution
2
- module Consistency
1
+ module Cassie::Statements
2
+ def self.default_consistency
3
+ return @default_consistency if defined?(@default_consistency)
4
+ nil
5
+ end
6
+
7
+ def self.default_consistency=(val)
8
+ @default_consistency = val
9
+ end
10
+
11
+ module Execution::Consistency
3
12
  extend ActiveSupport::Concern
4
13
 
5
14
  included do
@@ -8,7 +17,7 @@ module Cassie::Statements::Execution
8
17
 
9
18
  module ClassMethods
10
19
  def inherited(subclass)
11
- subclass.consistency = consistency
20
+ subclass.consistency = consistency if defined?(@consistency)
12
21
  super
13
22
  end
14
23
 
@@ -18,7 +27,8 @@ module Cassie::Statements::Execution
18
27
 
19
28
  def consistency(val=:get)
20
29
  if val == :get
21
- @consistency if defined?(@consistency)
30
+ return @consistency if defined?(@consistency)
31
+ Cassie::Statements.default_consistency
22
32
  else
23
33
  self.consistency = val
24
34
  end
@@ -0,0 +1,3 @@
1
+ module Cassie
2
+ VERSION = "1.0.0.beta.22"
3
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cassie
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.beta.21
4
+ version: 1.0.0.beta.22
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Prothro
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-10-12 00:00:00.000000000 Z
11
+ date: 2016-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cassandra-driver
@@ -58,6 +58,34 @@ dependencies:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
60
  version: '3.4'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rake
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '11.3'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '11.3'
75
+ - !ruby/object:Gem::Dependency
76
+ name: gem-release
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: 0.7.4
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: 0.7.4
61
89
  - !ruby/object:Gem::Dependency
62
90
  name: byebug
63
91
  requirement: !ruby/object:Gem::Requirement
@@ -190,6 +218,7 @@ files:
190
218
  - lib/cassie/testing/fake/result.rb
191
219
  - lib/cassie/testing/fake/session.rb
192
220
  - lib/cassie/testing/fake/session_methods.rb
221
+ - lib/cassie/version.rb
193
222
  homepage: https://github.com/eprothro/cassie
194
223
  licenses:
195
224
  - MIT