cassie 1.0.0.beta.17 → 1.0.0.beta.21

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.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/bin/cassie +40 -15
  3. data/lib/cassie/configuration/templates/cassandra.yml +1 -2
  4. data/lib/cassie/connection.rb +3 -3
  5. data/lib/cassie/connection_handler/cluster.rb +1 -1
  6. data/lib/cassie/connection_handler/sessions.rb +1 -1
  7. data/lib/cassie/connection_handler.rb +4 -2
  8. data/lib/cassie/definition.rb +8 -0
  9. data/lib/cassie/modification.rb +9 -0
  10. data/lib/cassie/query.rb +3 -15
  11. data/lib/cassie/statements/README.md +710 -0
  12. data/lib/cassie/statements/core.rb +23 -0
  13. data/lib/cassie/{queries/statement/batches.rb → statements/execution/batched_fetching.rb} +7 -11
  14. data/lib/cassie/{queries/statement → statements/execution}/callbacks.rb +1 -1
  15. data/lib/cassie/{queries/statement → statements/execution}/consistency.rb +1 -1
  16. data/lib/cassie/statements/execution/deserialization.rb +13 -0
  17. data/lib/cassie/{queries/statement → statements/execution}/fetching.rb +10 -21
  18. data/lib/cassie/{queries/instrumentation/execution.rb → statements/execution/instrumentation.rb} +6 -2
  19. data/lib/cassie/statements/execution/partition_linking/cursoring_policy.rb +13 -0
  20. data/lib/cassie/statements/execution/partition_linking/policy_methods.rb +128 -0
  21. data/lib/cassie/statements/execution/partition_linking/simple_policy.rb +19 -0
  22. data/lib/cassie/statements/execution/partition_linking.rb +49 -0
  23. data/lib/cassie/statements/execution/peeking.rb +28 -0
  24. data/lib/cassie/statements/execution/results/core.rb +11 -0
  25. data/lib/cassie/statements/execution/results/cursored_result.rb +26 -0
  26. data/lib/cassie/statements/execution/results/instrumentation.rb +18 -0
  27. data/lib/cassie/statements/execution/results/modification.rb +12 -0
  28. data/lib/cassie/statements/execution/results/modification_result.rb +8 -0
  29. data/lib/cassie/statements/execution/results/peeking.rb +42 -0
  30. data/lib/cassie/statements/execution/results/peeking_result.rb +10 -0
  31. data/lib/cassie/statements/execution/results/query_result.rb +9 -0
  32. data/lib/cassie/statements/execution/results/querying.rb +66 -0
  33. data/lib/cassie/statements/execution/results/result.rb +23 -0
  34. data/lib/cassie/statements/execution/results.rb +12 -0
  35. data/lib/cassie/statements/execution.rb +69 -0
  36. data/lib/cassie/statements/instrumenting.rb +6 -0
  37. data/lib/cassie/{queries/logging/building_resources_event.rb → statements/logging/deserialize_event.rb} +4 -4
  38. data/lib/cassie/statements/logging/deserialize_subscriber.rb +19 -0
  39. data/lib/cassie/{queries/logging/cql_execution_event.rb → statements/logging/execute_event.rb} +8 -4
  40. data/lib/cassie/statements/logging/execute_subscriber.rb +19 -0
  41. data/lib/cassie/statements/logging.rb +12 -0
  42. data/lib/cassie/statements/modification.rb +14 -0
  43. data/lib/cassie/statements/query.rb +12 -0
  44. data/lib/cassie/statements/statement/assignment.rb +51 -0
  45. data/lib/cassie/statements/statement/assignments.rb +87 -0
  46. data/lib/cassie/{queries → statements}/statement/conditions.rb +1 -3
  47. data/lib/cassie/{queries → statements}/statement/deleting.rb +15 -12
  48. data/lib/cassie/{queries → statements}/statement/inserting.rb +13 -10
  49. data/lib/cassie/statements/statement/limiting.rb +89 -0
  50. data/lib/cassie/{queries → statements}/statement/mapping.rb +21 -41
  51. data/lib/cassie/{queries → statements}/statement/ordering.rb +1 -1
  52. data/lib/cassie/statements/statement/pagination/cursors.rb +112 -0
  53. data/lib/cassie/statements/statement/pagination.rb +19 -0
  54. data/lib/cassie/{queries → statements}/statement/preparation/cache.rb +1 -1
  55. data/lib/cassie/{queries → statements}/statement/preparation.rb +4 -5
  56. data/lib/cassie/statements/statement/relation.rb +68 -0
  57. data/lib/cassie/statements/statement/relations.rb +93 -0
  58. data/lib/cassie/statements/statement/selection.rb +86 -0
  59. data/lib/cassie/{queries → statements}/statement/updating.rb +9 -10
  60. data/lib/cassie/{queries → statements}/statement.rb +10 -20
  61. data/lib/cassie/statements.rb +9 -0
  62. data/lib/cassie/testing/fake/definition.rb +11 -0
  63. data/lib/cassie/testing/fake/modification.rb +11 -0
  64. data/lib/cassie/testing/fake/result.rb +15 -3
  65. data/lib/cassie/testing.rb +2 -0
  66. data/lib/cassie.rb +2 -0
  67. metadata +57 -34
  68. data/lib/cassie/queries/README.md +0 -458
  69. data/lib/cassie/queries/instrumentation/loading.rb +0 -15
  70. data/lib/cassie/queries/instrumentation.rb +0 -18
  71. data/lib/cassie/queries/logging/subscription.rb +0 -24
  72. data/lib/cassie/queries/logging.rb +0 -21
  73. data/lib/cassie/queries/statement/assignment.rb +0 -36
  74. data/lib/cassie/queries/statement/assignments.rb +0 -67
  75. data/lib/cassie/queries/statement/execution.rb +0 -45
  76. data/lib/cassie/queries/statement/limiting.rb +0 -36
  77. data/lib/cassie/queries/statement/loading.rb +0 -24
  78. data/lib/cassie/queries/statement/pagination/cursors.rb +0 -168
  79. data/lib/cassie/queries/statement/pagination/page_size.rb +0 -7
  80. data/lib/cassie/queries/statement/pagination.rb +0 -37
  81. data/lib/cassie/queries/statement/relation.rb +0 -74
  82. data/lib/cassie/queries/statement/relations.rb +0 -66
  83. data/lib/cassie/queries/statement/selection.rb +0 -63
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.17
4
+ version: 1.0.0.beta.21
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-09-01 00:00:00.000000000 Z
11
+ date: 2016-10-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cassandra-driver
@@ -123,45 +123,68 @@ files:
123
123
  - lib/cassie/connection_handler/README.md
124
124
  - lib/cassie/connection_handler/cluster.rb
125
125
  - lib/cassie/connection_handler/sessions.rb
126
+ - lib/cassie/definition.rb
126
127
  - lib/cassie/logger.rb
127
- - lib/cassie/queries/README.md
128
- - lib/cassie/queries/instrumentation.rb
129
- - lib/cassie/queries/instrumentation/execution.rb
130
- - lib/cassie/queries/instrumentation/loading.rb
131
- - lib/cassie/queries/logging.rb
132
- - lib/cassie/queries/logging/building_resources_event.rb
133
- - lib/cassie/queries/logging/cql_execution_event.rb
134
- - lib/cassie/queries/logging/subscription.rb
135
- - lib/cassie/queries/statement.rb
136
- - lib/cassie/queries/statement/assignment.rb
137
- - lib/cassie/queries/statement/assignments.rb
138
- - lib/cassie/queries/statement/batches.rb
139
- - lib/cassie/queries/statement/callbacks.rb
140
- - lib/cassie/queries/statement/conditions.rb
141
- - lib/cassie/queries/statement/consistency.rb
142
- - lib/cassie/queries/statement/deleting.rb
143
- - lib/cassie/queries/statement/execution.rb
144
- - lib/cassie/queries/statement/fetching.rb
145
- - lib/cassie/queries/statement/inserting.rb
146
- - lib/cassie/queries/statement/limiting.rb
147
- - lib/cassie/queries/statement/loading.rb
148
- - lib/cassie/queries/statement/mapping.rb
149
- - lib/cassie/queries/statement/ordering.rb
150
- - lib/cassie/queries/statement/pagination.rb
151
- - lib/cassie/queries/statement/pagination/cursors.rb
152
- - lib/cassie/queries/statement/pagination/page_size.rb
153
- - lib/cassie/queries/statement/preparation.rb
154
- - lib/cassie/queries/statement/preparation/cache.rb
155
- - lib/cassie/queries/statement/relation.rb
156
- - lib/cassie/queries/statement/relations.rb
157
- - lib/cassie/queries/statement/selection.rb
158
- - lib/cassie/queries/statement/updating.rb
128
+ - lib/cassie/modification.rb
159
129
  - lib/cassie/query.rb
130
+ - lib/cassie/statements.rb
131
+ - lib/cassie/statements/README.md
132
+ - lib/cassie/statements/core.rb
133
+ - lib/cassie/statements/execution.rb
134
+ - lib/cassie/statements/execution/batched_fetching.rb
135
+ - lib/cassie/statements/execution/callbacks.rb
136
+ - lib/cassie/statements/execution/consistency.rb
137
+ - lib/cassie/statements/execution/deserialization.rb
138
+ - lib/cassie/statements/execution/fetching.rb
139
+ - lib/cassie/statements/execution/instrumentation.rb
140
+ - lib/cassie/statements/execution/partition_linking.rb
141
+ - lib/cassie/statements/execution/partition_linking/cursoring_policy.rb
142
+ - lib/cassie/statements/execution/partition_linking/policy_methods.rb
143
+ - lib/cassie/statements/execution/partition_linking/simple_policy.rb
144
+ - lib/cassie/statements/execution/peeking.rb
145
+ - lib/cassie/statements/execution/results.rb
146
+ - lib/cassie/statements/execution/results/core.rb
147
+ - lib/cassie/statements/execution/results/cursored_result.rb
148
+ - lib/cassie/statements/execution/results/instrumentation.rb
149
+ - lib/cassie/statements/execution/results/modification.rb
150
+ - lib/cassie/statements/execution/results/modification_result.rb
151
+ - lib/cassie/statements/execution/results/peeking.rb
152
+ - lib/cassie/statements/execution/results/peeking_result.rb
153
+ - lib/cassie/statements/execution/results/query_result.rb
154
+ - lib/cassie/statements/execution/results/querying.rb
155
+ - lib/cassie/statements/execution/results/result.rb
156
+ - lib/cassie/statements/instrumenting.rb
157
+ - lib/cassie/statements/logging.rb
158
+ - lib/cassie/statements/logging/deserialize_event.rb
159
+ - lib/cassie/statements/logging/deserialize_subscriber.rb
160
+ - lib/cassie/statements/logging/execute_event.rb
161
+ - lib/cassie/statements/logging/execute_subscriber.rb
162
+ - lib/cassie/statements/modification.rb
163
+ - lib/cassie/statements/query.rb
164
+ - lib/cassie/statements/statement.rb
165
+ - lib/cassie/statements/statement/assignment.rb
166
+ - lib/cassie/statements/statement/assignments.rb
167
+ - lib/cassie/statements/statement/conditions.rb
168
+ - lib/cassie/statements/statement/deleting.rb
169
+ - lib/cassie/statements/statement/inserting.rb
170
+ - lib/cassie/statements/statement/limiting.rb
171
+ - lib/cassie/statements/statement/mapping.rb
172
+ - lib/cassie/statements/statement/ordering.rb
173
+ - lib/cassie/statements/statement/pagination.rb
174
+ - lib/cassie/statements/statement/pagination/cursors.rb
175
+ - lib/cassie/statements/statement/preparation.rb
176
+ - lib/cassie/statements/statement/preparation/cache.rb
177
+ - lib/cassie/statements/statement/relation.rb
178
+ - lib/cassie/statements/statement/relations.rb
179
+ - lib/cassie/statements/statement/selection.rb
180
+ - lib/cassie/statements/statement/updating.rb
160
181
  - lib/cassie/support.rb
161
182
  - lib/cassie/support/command_runner.rb
162
183
  - lib/cassie/testing.rb
163
184
  - lib/cassie/testing/README.md
185
+ - lib/cassie/testing/fake/definition.rb
164
186
  - lib/cassie/testing/fake/execution_info.rb
187
+ - lib/cassie/testing/fake/modification.rb
165
188
  - lib/cassie/testing/fake/prepared_statement.rb
166
189
  - lib/cassie/testing/fake/query.rb
167
190
  - lib/cassie/testing/fake/result.rb
@@ -1,458 +0,0 @@
1
- # Cassie Queries
2
-
3
- `cassie` query classes aim to provide a query interface that is
4
-
5
- * Easy to use
6
- * Easy to understand (and thus maintain)
7
- * Easy to test
8
- * Works well with the data mapper design pattern
9
-
10
- ### Usage
11
-
12
- You might expect to see class methods allowing queries to be built like such:
13
-
14
- ```
15
- Cassie.insert(:users_by_username,
16
- "id = #{some_id}",
17
- username: some_username)
18
- ```
19
-
20
- Queries defined on the fly like this tend to create debt for an application in the long term. They:
21
- * create gaps in test coverage
22
- * resist documentation
23
- * resist refactoring
24
-
25
- Application queries represent distinct application behavior, `cassie` queries are designed to help create query classes that are reusable, testable and maintainable (so you can sleep better at night).
26
-
27
- ```ruby
28
- # Some PORO user model
29
- user = User.new(username: username)
30
-
31
- MyInsertionQuery.new.insert(user)
32
- ```
33
- <pre><b>
34
- (1.2ms) INSERT INTO users_by_username (id, username) VALUES (?, ?); [["uuid()", "eprothro"]]
35
- </b></pre>
36
-
37
- ```ruby
38
- class MyInsertionQuery < Cassie::Query
39
-
40
- insert :users_by_username do |u|
41
- u.id,
42
- u.username
43
- end
44
-
45
- def id
46
- "uuid()"
47
- end
48
- end
49
- ```
50
-
51
- CQL algebra is less complex than with SQL. So, rather than introducing a query abstraction layer (e.g. something like [arel](https://github.com/rails/arel)), `cassie` queries provide a lightweight CQL DSL to codify your CQL queries.
52
-
53
- ```sql
54
- SELECT *
55
- FROM posts_by_author_category
56
- WHERE author_id = ?
57
- AND category = ?
58
- LIMIT 30;
59
- ```
60
- ```ruby
61
- select :posts_by_author_category
62
- where :author_id, :eq
63
- where :category, :eq
64
- limit 30
65
- ```
66
-
67
- This maintains the clarity of your CQL, allowing you to be expressive, but still use additional features without having get crazy with string manipulation.
68
-
69
- #### Dynamic term values
70
-
71
- ```ruby
72
- select :posts_by_author
73
-
74
- where :user_id, :eq
75
- ```
76
-
77
- Defining a CQL relation in a cassie query (the "where") creates a setter and getter for that relation. This allows the term value to be set for a particular query instance.
78
-
79
- ```ruby
80
- query.user_id = 123
81
- query.fetch
82
- => [#<Struct user_id=123, id="some post id">]
83
- ```
84
-
85
- <pre><b>
86
- (2.9ms) SELECT * FROM posts_by_author WHERE user_id = ? LIMIT 1; [[123]]
87
- </b></pre>
88
-
89
- These methods are plain old attr_accessors, and may be overriden
90
-
91
- ```ruby
92
- select :posts_by_author
93
-
94
- where :user_id, :eq
95
-
96
- def author=(user)
97
- @user_id = user.id
98
- end
99
- ```
100
-
101
- ```ruby
102
- query.author = User.new(id: 123)
103
- query.fetch
104
- => [#<Struct user_id=123, id="some post id">]
105
- ```
106
-
107
- <pre><b>
108
- (2.9ms) SELECT * FROM posts_by_author WHERE user_id = ? LIMIT 1; [[123]]
109
- </b></pre>
110
-
111
- A specific name can be provided for the setter/getter:
112
-
113
- ```ruby
114
- select :posts_by_author
115
-
116
- where :user_id, :eq, value: :author_id
117
- ```
118
-
119
- ```ruby
120
- query.author_id = 123
121
- query.fetch
122
- => [#<Struct user_id=123, id="some post id">]
123
- ```
124
-
125
- <pre><b>
126
- (2.9ms) SELECT * FROM posts_by_author WHERE user_id = ? LIMIT 1; [[123]]
127
- </b></pre>
128
-
129
- #### Conditional relations
130
-
131
- ```ruby
132
- select :posts_by_author_category
133
-
134
- where :author_id, :eq
135
- where :category, :eq, if: "category.present?"
136
- ```
137
-
138
- or
139
-
140
- ```ruby
141
- select :posts_by_author_category
142
-
143
- where :author_id, :eq
144
- where :category, :eq, if: :filter_by_category?
145
-
146
- def filter_by_category?
147
- #true or false, as makes sense for your query
148
- end
149
- ```
150
-
151
- #### Consistency configuration
152
-
153
- 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.
154
-
155
- ```ruby
156
- Cassie.configuration[:consistency]
157
- => nil
158
-
159
- Cassie.cluster.instance_variable_get(:@execution_options).consistency
160
- => :one
161
- ```
162
-
163
- A Cassie::Query looks 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.
164
-
165
- ```ruby
166
- select :posts_by_author_category
167
-
168
- where :author_id, :eq
169
- where :category, :eq, if: :filter_by_category?
170
-
171
- def filter_by_category?
172
- #true or false, as makes sense for your query
173
- end
174
-
175
- def consistency
176
- #dynamically determine a query object's consistency level
177
- if filter_by_category?
178
- :quorum
179
- else
180
- super
181
- end
182
- end
183
- ```
184
-
185
- ```ruby
186
- select :posts_by_author_category
187
-
188
- where :author_id, :eq
189
- where :category, :eq
190
-
191
- consistency :quorum
192
- ```
193
-
194
- ```ruby
195
- # lib/tasks/interesting_task.rake
196
- require_relative "interesting_worker"
197
-
198
- task :interesting_task do
199
- Cassandra::Query.consistency = :all
200
-
201
- InterestingWorker.new.perform
202
- end
203
- ```
204
-
205
- #### Finders
206
-
207
- 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.
208
-
209
- ##### `fetch`
210
-
211
- Executes the query; returns array of results.
212
-
213
- ```
214
- UsersByResourceQuery.new.fetch(resource: some_resource)
215
- => [#<User id=:123, username=:eprothro>, #<User id=:456, username=:tenderlove>]
216
- ```
217
-
218
- ##### `fetch_first` and `fetch_first!`
219
-
220
- Executes the query, temporarily limited to 1 result; returns a single result. Bang version raises if no result is found.
221
-
222
- ```
223
- UsersByUsernameQuery.new.fetch_first(username: "eprothro").username
224
- => "eprothro"
225
- ```
226
-
227
- ```
228
- UsersByUsernameQuery.new.fetch_first(username: "active record").username
229
- Cassie::Queries::RecordNotFound: CQL row does not exist
230
- ```
231
-
232
- ##### Batching
233
-
234
- Similar to [Rails Batching](http://guides.rubyonrails.org/v4.2/active_record_querying.html#retrieving-multiple-objects-in-batches), Cassie allows efficient batching of `SELECT` queries.
235
-
236
- ###### `fetch_each`
237
- ```
238
- UsersQuery.new.fetch_each do |user|
239
- # only 1000 queried and loaded at a time
240
- end
241
- ```
242
-
243
- ```
244
- UsersQuery.new.fetch_each(batch_size: 500) do |user|
245
- # only 500 queried and loaded at a time
246
- end
247
- ```
248
-
249
- ```
250
- UsersQuery.new.fetch_each.with_index do |user, index|
251
- # Enumerator chaining without a block
252
- end
253
- ```
254
- ###### `fetch_in_batches`
255
- ```
256
- UsersQuery.new.fetch_in_batches do |users_array|
257
- # only 1000 queried and at a time
258
- end
259
- ```
260
-
261
- ```
262
- UsersQuery.new.fetch_in_batches(batch_size: 500) do |users_array|
263
- # only 500 queried and at a time
264
- end
265
- ```
266
-
267
- ```
268
- UsersQuery.new.fetch_in_batches.with_index do |group, index|
269
- # Enumerator chaining without a block
270
- end
271
- ```
272
-
273
- #### Object Mapping
274
- For Selection Queries, resources are returned as structs by default for manipulation using accessor methods.
275
-
276
- ```ruby
277
- UsersByUsernameQuery.new.fetch(username: "eprothro")
278
- => [#<Struct id=:123, username=:eprothro>]
279
-
280
- UsersByUsernameQuery.new.fetch_first(username: "eprothro").username
281
- => "eprothro"
282
- ```
283
-
284
- Most application will want to override `build_resource` to construct more useful domain objects
285
-
286
- ```
287
- class UsersByUsernameQuery < Cassie::Query
288
-
289
- select :users_by_username
290
-
291
- where :username, :eq
292
-
293
- def build_resource(row)
294
- User.new(row)
295
- end
296
- end
297
- ```
298
-
299
- ```ruby
300
- UsersByUsernameQuery.new.fetch_first(username: "eprothro")
301
- => #<User:0x007fedec219cd8 @id=123, @username="eprothro">
302
- ```
303
-
304
- For Data Modification Queries (`insert`, `update`, `delete`), mapping binding values from a domain object is supported.
305
-
306
- ```ruby
307
- class UpdateUserQuery < Cassandra::Query
308
-
309
- update :users_by_id do |q|
310
- q.set :phone
311
- q.set :email
312
- q.set :address
313
- q.set :username
314
- end
315
-
316
- where :id, :eq
317
-
318
- map_from :user
319
- ```
320
-
321
- This allows a domain object to be passed to the modification method, where binding values will be retrieved from the object
322
-
323
- ```ruby
324
- user
325
- => #<User:0x007ff8895ce660 @id=6539, @phone="+15555555555", @email="etp@example.com", @address=nil, @username= "etp">
326
- UpdateUserQuery.new.update(user)
327
- ```
328
-
329
- <pre><b>
330
- (1.2ms) UPDATE users_by_id (phone, email, address, username) VALUES (?, ?, ?, ?) WHERE id = ?; [["+15555555555", "etp@example.com", nil, "etp", 6539]]
331
- </b></pre>
332
-
333
-
334
- #### Cursored paging
335
-
336
- Read about [cursored pagination](https://www.google.com/webhp?q=cursored%20paging#safe=off&q=cursor+paging) if unfamiliar with concept and how it optimizes paging through frequently updated data sets and I/O bandwidth.
337
-
338
- ```ruby
339
- class MyPagedQuery < Cassie::Query
340
-
341
- select :events_by_user
342
-
343
- where :user_id, :eq
344
-
345
- max_cursor :event_id
346
- since_cursor :event_id
347
- end
348
- ```
349
-
350
- ```ruby
351
- # Imagine a set of id's 100 decreasing to 1
352
- # where the client already has 1-50 in memory.
353
-
354
- q = MyPagedQuery.new(page_size: 25, user: current_user)
355
-
356
- # fetch 100 - 76
357
- page_1 = q.fetch(max_event_id: nil, since_event_id: 50)
358
- q.next_max_event_id
359
- # => 75
360
-
361
- # fetch 75 - 51
362
- page_2 = q.fetch(max_event_id: q.next_max_event_id, since_event_id: 50)
363
- q.next_max_id
364
- # => nil
365
- ```
366
-
367
- The `cursor_by` helper can be used as shorthand for defining these relations for which you wish to use cursors.
368
- ```ruby
369
- class MyPagedQuery < Cassie::Query
370
-
371
- select :events_by_user
372
-
373
- where :user_id, :eq
374
-
375
- cursor_by :event_id
376
- end
377
- ```
378
-
379
- #### Prepared statements
380
-
381
- A `Cassie::Query` will use prepared statements by default, cacheing prepared statements across all Cassie::Query objects, keyed by the bound CQL string.
382
-
383
-
384
- To not use prepared statements for a particular query, disable the `.prepare` class option.
385
-
386
- ```ruby
387
- class MySpecialQuery < Cassie::Query
388
-
389
- select :users_by_some_value do
390
- where :bucket
391
- where :some_value, :in
392
- end
393
-
394
- # the length of `some_values` that will be passed in
395
- # is highly variable, so we don't want to incur the
396
- # cost of preparing a statement for each unique length
397
- self.prepare = false
398
- end
399
- ```
400
-
401
- ```ruby
402
- query = MySpecialQuery.new
403
-
404
- # will not prepare statement
405
- set_1 = query.fetch([1, 2, 3])
406
- # will not prepare statement
407
- set_2 = query.fetch([7, 8, 9, 10, 11, 12])
408
- ```
409
-
410
- #### Unbound statements
411
-
412
- Cassie Query features are built around bound statements. However, we've tried to keep a simple ruby design in place to make custom behavior easier. If you want to override the assumption of bound statements, simply override `#statement`, returnign something that a `Cassandra::Session` can execute.
413
-
414
- ```ruby
415
- class NotSureWhyIWouldDoThisButHereItIsQuery < Cassie::Query
416
- def statement
417
- "SELECT * FROM users WHERE id IN (1,2,3);"
418
- end
419
- end
420
- ```
421
-
422
- #### Logging
423
-
424
- Cassie Query objects use the Cassie logger unless overridden. This logs to STDOUT by default. Set any log stream you wish.
425
-
426
- ```ruby
427
- Cassie.logger = my_app.config.logger
428
- ```
429
-
430
- Set the log level to `debug` in order to log execution details.
431
-
432
- ```ruby
433
- Cassie::Query.logger.level = Logger::DEBUG
434
- ```
435
-
436
- #### Execution Time
437
-
438
- Cassie Queries instrument execution time as `cassie.cql.execution` and logs a debug message.
439
-
440
- ```ruby
441
- SelectUserByUsernameQuery.new('some_user').execute
442
- (5.5ms) SELECT * FROM users_by_username WHERE username = ? LIMIT 1; ["some_user"] [LOCAL_ONE]
443
- ```
444
- This measures the time to build the CQL query (statement and bindings), transmit the query to the cassandra coordinator, receive the result from the cassandra coordinator, and have the cassandra ruby driver build the ruby representation of the results. It does not include the time it takes for the Cassie Query to build its resource objects.
445
-
446
- #### Resource Loading
447
-
448
- Cassie Queries instrument resource building as `cassie.building_resources` and logs a debug message.
449
-
450
- ```ruby
451
- SelectUserByUsernameQuery.new('some_user').fetch
452
- (5.5ms) SELECT * FROM users_by_username WHERE username = ? LIMIT 1; ["some_user"] [LOCAL_ONE]
453
- (0.2ms) 1 resource object built from Cassandra query result
454
- ```
455
-
456
- This measures the time it takes Cassie to build the resource objects (e.g. your domain objects) and is in addition to the execution time.
457
-
458
- > fetch time = `cassie.cql.execution` time + `cassie.building_resources` time
@@ -1,15 +0,0 @@
1
- module Cassie::Queries::Instrumentation
2
- module Loading
3
-
4
- protected
5
-
6
- def build_resources(rows)
7
- instrumenter.instrument("cassie.building_resources") do |payload|
8
- payload[:count] = rows.count if rows.respond_to?(:count)
9
- super
10
- end
11
- end
12
- end
13
- end
14
-
15
-
@@ -1,18 +0,0 @@
1
- require_relative 'instrumentation/execution'
2
- require_relative 'instrumentation/loading'
3
-
4
- module Cassie::Queries
5
- module Instrumentation
6
- extend ::ActiveSupport::Concern
7
-
8
- included do
9
- include Execution
10
- end
11
-
12
- protected
13
-
14
- def instrumenter
15
- ActiveSupport::Notifications
16
- end
17
- end
18
- end
@@ -1,24 +0,0 @@
1
- require_relative 'cql_execution_event'
2
- require_relative 'building_resources_event'
3
-
4
- module Cassie::Queries::Logging
5
- module Subscription
6
- extend ::ActiveSupport::Concern
7
-
8
- included do
9
- ActiveSupport::Notifications.subscribe('cassie.cql.execution') do |*args|
10
- # don't log if instrumentation failed
11
- unless args.last[:exception]
12
- logger.debug(CqlExecutionEvent.new(*args).message)
13
- end
14
- end
15
-
16
- ActiveSupport::Notifications.subscribe('cassie.building_resources') do |*args|
17
- # don't log if instrumentation failed
18
- unless args.last[:exception]
19
- logger.debug(BuildingResourcesEvent.new(*args).message)
20
- end
21
- end
22
- end
23
- end
24
- end
@@ -1,21 +0,0 @@
1
- require_relative 'logging/subscription'
2
-
3
- module Cassie::Queries
4
- module Logging
5
- extend ::ActiveSupport::Concern
6
-
7
- included do
8
- include Subscription
9
- end
10
-
11
- module ClassMethods
12
- def logger
13
- Cassie.logger
14
- end
15
- end
16
-
17
- def logger
18
- self.class.logger
19
- end
20
- end
21
- end
@@ -1,36 +0,0 @@
1
- module Cassie::Queries::Statement
2
- # set "username = ?", value: :username
3
- # set "favs = favs + ?" value: "{ 'movie' : 'Cassablanca' }"
4
- # set :username
5
- class Assignment
6
- # https://cassandra.apache.org/doc/cql3/CQL.html#updateStmt
7
-
8
- attr_reader :identifier
9
-
10
- def initialize(identifier, opts={})
11
- if String === identifier
12
- # custom assignment is being defined:
13
- #
14
- # `assign "username = ?", value: :username`
15
- @cql = identifier
16
- @custom = true
17
- else
18
- @identifier = identifier
19
- end
20
- end
21
-
22
- def to_insert_cql
23
- return @cql if defined?(@cql)
24
- identifier
25
- end
26
-
27
- def to_update_cql
28
- return @cql if defined?(@cql)
29
- "#{identifier} = ?"
30
- end
31
-
32
- def custom?
33
- !!@custom
34
- end
35
- end
36
- end