cassie-queries 0.0.1.a4 → 0.0.1.alpha.5
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.
- checksums.yaml +4 -4
- metadata +4 -31
- data/lib/cassie/queries/instrumentation.rb +0 -24
- data/lib/cassie/queries/logging/cql_execution_event.rb +0 -44
- data/lib/cassie/queries/logging/logger.rb +0 -27
- data/lib/cassie/queries/logging/subscription.rb +0 -22
- data/lib/cassie/queries/logging.rb +0 -22
- data/lib/cassie/queries/pagination/cursors.rb +0 -15
- data/lib/cassie/queries/pagination/page_size.rb +0 -7
- data/lib/cassie/queries/pagination.rb +0 -37
- data/lib/cassie/queries/session.rb +0 -22
- data/lib/cassie/queries/statement/assignment.rb +0 -36
- data/lib/cassie/queries/statement/assignments.rb +0 -67
- data/lib/cassie/queries/statement/deleting.rb +0 -60
- data/lib/cassie/queries/statement/fetching.rb +0 -55
- data/lib/cassie/queries/statement/inserting.rb +0 -37
- data/lib/cassie/queries/statement/limiting.rb +0 -25
- data/lib/cassie/queries/statement/loading.rb +0 -16
- data/lib/cassie/queries/statement/mapping.rb +0 -66
- data/lib/cassie/queries/statement/ordering.rb +0 -11
- data/lib/cassie/queries/statement/preparation/cache.rb +0 -55
- data/lib/cassie/queries/statement/preparation.rb +0 -47
- data/lib/cassie/queries/statement/relation.rb +0 -59
- data/lib/cassie/queries/statement/relations.rb +0 -64
- data/lib/cassie/queries/statement/selection.rb +0 -63
- data/lib/cassie/queries/statement/updating.rb +0 -39
- data/lib/cassie/queries/statement.rb +0 -99
- data/lib/cassie/query.rb +0 -25
- data/lib/cassie-queries.rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 24b13bcc78da6a2d63d65cdf05e117668e1f579f
|
4
|
+
data.tar.gz: c3fde5752744563dc4a1e335d62bc2c62b515600
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7608f07e36d0ee0cf82d02b1cc84d0a17ab0967ac66f7964ce1bc0820135dd225a3f564fa431b6125693c6e999ce2797725972b7f17331598865f47013f82b63
|
7
|
+
data.tar.gz: 1d5a2f4d059f160477f7ad0dcc7d48e61006c64aa4b6cf50a412ff5c12b4994794af5e7f363a3c6d5e166590c8fed8611dc6999165f325f6a56bb7f985857e16
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cassie-queries
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.1.
|
4
|
+
version: 0.0.1.alpha.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evan Prothro
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cassandra-driver
|
@@ -86,35 +86,8 @@ email: evan.prothro@gmail.com
|
|
86
86
|
executables: []
|
87
87
|
extensions: []
|
88
88
|
extra_rdoc_files: []
|
89
|
-
files:
|
90
|
-
|
91
|
-
- lib/cassie/queries/instrumentation.rb
|
92
|
-
- lib/cassie/queries/logging.rb
|
93
|
-
- lib/cassie/queries/logging/cql_execution_event.rb
|
94
|
-
- lib/cassie/queries/logging/logger.rb
|
95
|
-
- lib/cassie/queries/logging/subscription.rb
|
96
|
-
- lib/cassie/queries/pagination.rb
|
97
|
-
- lib/cassie/queries/pagination/cursors.rb
|
98
|
-
- lib/cassie/queries/pagination/page_size.rb
|
99
|
-
- lib/cassie/queries/session.rb
|
100
|
-
- lib/cassie/queries/statement.rb
|
101
|
-
- lib/cassie/queries/statement/assignment.rb
|
102
|
-
- lib/cassie/queries/statement/assignments.rb
|
103
|
-
- lib/cassie/queries/statement/deleting.rb
|
104
|
-
- lib/cassie/queries/statement/fetching.rb
|
105
|
-
- lib/cassie/queries/statement/inserting.rb
|
106
|
-
- lib/cassie/queries/statement/limiting.rb
|
107
|
-
- lib/cassie/queries/statement/loading.rb
|
108
|
-
- lib/cassie/queries/statement/mapping.rb
|
109
|
-
- lib/cassie/queries/statement/ordering.rb
|
110
|
-
- lib/cassie/queries/statement/preparation.rb
|
111
|
-
- lib/cassie/queries/statement/preparation/cache.rb
|
112
|
-
- lib/cassie/queries/statement/relation.rb
|
113
|
-
- lib/cassie/queries/statement/relations.rb
|
114
|
-
- lib/cassie/queries/statement/selection.rb
|
115
|
-
- lib/cassie/queries/statement/updating.rb
|
116
|
-
- lib/cassie/query.rb
|
117
|
-
homepage: https://github.com/eprothro/cassie-queries
|
89
|
+
files: []
|
90
|
+
homepage: https://github.com/eprothro/cassie/tree/master/queries
|
118
91
|
licenses:
|
119
92
|
- MIT
|
120
93
|
metadata: {}
|
@@ -1,24 +0,0 @@
|
|
1
|
-
module Cassie::Queries
|
2
|
-
module Instrumentation
|
3
|
-
extend ::ActiveSupport::Concern
|
4
|
-
|
5
|
-
def execute
|
6
|
-
instrument { super }
|
7
|
-
end
|
8
|
-
|
9
|
-
def instrument #:nodoc:
|
10
|
-
instrumenter.instrument("cql.execute") do |payload|
|
11
|
-
execution_val = yield # execution populates #result
|
12
|
-
|
13
|
-
payload[:execution_info] = result.execution_info if result.respond_to?(:execution_info)
|
14
|
-
execution_val
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
protected
|
19
|
-
|
20
|
-
def instrumenter
|
21
|
-
ActiveSupport::Notifications
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
module Cassie::Queries::Logging
|
2
|
-
class CqlExecutionEvent < ActiveSupport::Notifications::Event
|
3
|
-
|
4
|
-
def duration # in milliseconds
|
5
|
-
return super unless traced?
|
6
|
-
|
7
|
-
# trace duration is in microseconds
|
8
|
-
trace.duration / 1000.0
|
9
|
-
end
|
10
|
-
|
11
|
-
def message
|
12
|
-
color "(#{duration.round(1)}ms) #{statement}"
|
13
|
-
end
|
14
|
-
|
15
|
-
protected
|
16
|
-
|
17
|
-
def execution_info
|
18
|
-
payload[:execution_info]
|
19
|
-
end
|
20
|
-
|
21
|
-
def statement
|
22
|
-
if execution_info
|
23
|
-
statement = execution_info.statement
|
24
|
-
str = statement.cql
|
25
|
-
str += " [#{statement.params}]" if statement.respond_to? :params
|
26
|
-
str
|
27
|
-
else
|
28
|
-
"CQL executed: (`execution_info` was not present?)"
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def traced?
|
33
|
-
execution_info && !!trace
|
34
|
-
end
|
35
|
-
|
36
|
-
def trace
|
37
|
-
execution_info.trace
|
38
|
-
end
|
39
|
-
|
40
|
-
def color(message)
|
41
|
-
"\e[1m\e[37m#{message}\e[0m\e[22m"
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
module Cassie::Queries
|
2
|
-
module Logging
|
3
|
-
|
4
|
-
def self.logger
|
5
|
-
@logger ||= init_logger
|
6
|
-
end
|
7
|
-
|
8
|
-
def self.logger=(new_logger)
|
9
|
-
@logger = new_logger || Logger.new('/dev/null')
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.init_logger(target = STDOUT)
|
13
|
-
previous_logger = defined?(@logger) ? @logger : nil
|
14
|
-
|
15
|
-
@logger = Logger.new(target)
|
16
|
-
@logger.level = Logger::INFO
|
17
|
-
@logger.formatter = log_formatter
|
18
|
-
|
19
|
-
previous_logger.close if previous_logger
|
20
|
-
@logger
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.log_formatter
|
24
|
-
ActiveSupport::Logger::SimpleFormatter.new
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require_relative 'cql_execution_event'
|
2
|
-
|
3
|
-
module Cassie::Queries::Logging
|
4
|
-
module Subscription
|
5
|
-
extend ::ActiveSupport::Concern
|
6
|
-
|
7
|
-
included do
|
8
|
-
ActiveSupport::Notifications.subscribe('cql.execute') do |*args|
|
9
|
-
# args:
|
10
|
-
# name # => String, name of the event (such as 'render' from above)
|
11
|
-
# start # => Time, when the instrumented block started execution
|
12
|
-
# finish # => Time, when the instrumented block ended execution
|
13
|
-
# id # => String, unique ID for this notification
|
14
|
-
# payload # => Hash, the payload
|
15
|
-
# [:exception] => if raised during event
|
16
|
-
unless args.last[:exception]
|
17
|
-
logger.debug(CqlExecutionEvent.new(*args).message)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require_relative 'logging/logger'
|
2
|
-
require_relative 'logging/subscription'
|
3
|
-
|
4
|
-
module Cassie::Queries
|
5
|
-
module Logging
|
6
|
-
extend ::ActiveSupport::Concern
|
7
|
-
|
8
|
-
included do
|
9
|
-
include Subscription
|
10
|
-
end
|
11
|
-
|
12
|
-
module ClassMethods
|
13
|
-
def logger
|
14
|
-
Cassie::Queries::Logging.logger
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def logger
|
19
|
-
self.class.logger
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
module Cassie::Queries::Pagination
|
2
|
-
module Cursors
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
module ClassMethods
|
6
|
-
def max_cursor(field, opts={})
|
7
|
-
relation field, :lteq, opts
|
8
|
-
end
|
9
|
-
|
10
|
-
def since_cursor(field, opts={})
|
11
|
-
relation field, :gt, opts
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
require_relative 'pagination/cursors'
|
2
|
-
require_relative 'pagination/page_size'
|
3
|
-
|
4
|
-
module Cassie::Queries
|
5
|
-
module Pagination
|
6
|
-
extend ActiveSupport::Concern
|
7
|
-
|
8
|
-
included do
|
9
|
-
include Cursors
|
10
|
-
end
|
11
|
-
|
12
|
-
module ClassMethods
|
13
|
-
def inherited(subclass)
|
14
|
-
subclass.page_size = page_size
|
15
|
-
super
|
16
|
-
end
|
17
|
-
|
18
|
-
def page_size
|
19
|
-
return @page_size if defined?(@page_size)
|
20
|
-
Cassie::Queries::Pagination::PageSize.default
|
21
|
-
end
|
22
|
-
|
23
|
-
def page_size=(val)
|
24
|
-
@page_size = val
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def page_size
|
29
|
-
return @page_size if defined?(@page_size)
|
30
|
-
self.class.page_size
|
31
|
-
end
|
32
|
-
|
33
|
-
def page_size=(val)
|
34
|
-
@page_size = val
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module Cassie::Queries
|
2
|
-
module Session
|
3
|
-
extend ::ActiveSupport::Concern
|
4
|
-
|
5
|
-
module ClassMethods
|
6
|
-
def session
|
7
|
-
# until cassie-configuration exists,
|
8
|
-
# we're relying on the client to
|
9
|
-
# supply the session
|
10
|
-
if defined?(super)
|
11
|
-
super
|
12
|
-
else
|
13
|
-
raise "Oops! Cassie::Queries doesn't manage a Cassandra session for you, yet. You must provide a .session class method that returns a valid session."
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def session
|
19
|
-
self.class.session
|
20
|
-
end
|
21
|
-
end
|
22
|
-
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
|
@@ -1,67 +0,0 @@
|
|
1
|
-
require_relative 'assignment'
|
2
|
-
require_relative 'mapping'
|
3
|
-
|
4
|
-
module Cassie::Queries::Statement
|
5
|
-
module Assignments
|
6
|
-
extend ActiveSupport::Concern
|
7
|
-
|
8
|
-
included do
|
9
|
-
include Mapping
|
10
|
-
end
|
11
|
-
|
12
|
-
module ClassMethods
|
13
|
-
def set(identifier, opts={})
|
14
|
-
assignment = Assignment.new(identifier, opts)
|
15
|
-
opts[:value] ||= identifier.to_sym
|
16
|
-
|
17
|
-
if Symbol === opts[:value]
|
18
|
-
define_term_methods(opts[:value])
|
19
|
-
end
|
20
|
-
|
21
|
-
assignments[assignment] = opts
|
22
|
-
end
|
23
|
-
|
24
|
-
def assignments
|
25
|
-
@assignments ||= {}
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def assignments
|
30
|
-
self.class.assignments
|
31
|
-
end
|
32
|
-
|
33
|
-
def build_update_and_bindings
|
34
|
-
cql = ""
|
35
|
-
bindings = []
|
36
|
-
assignment_strings = []
|
37
|
-
|
38
|
-
assignments.each do |a, opts|
|
39
|
-
if eval_if_opt?(opts[:if])
|
40
|
-
assignment_strings << a.to_update_cql
|
41
|
-
bindings << eval_value_opt(opts[:value])
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
cql = "#{assignment_strings.join(', ')}" unless bindings.empty?
|
46
|
-
|
47
|
-
[cql , bindings]
|
48
|
-
end
|
49
|
-
|
50
|
-
def build_insert_and_bindings
|
51
|
-
identifiers = []
|
52
|
-
bindings = []
|
53
|
-
|
54
|
-
assignments.each do |a, opts|
|
55
|
-
if eval_if_opt?(opts[:if])
|
56
|
-
identifiers << a.to_insert_cql
|
57
|
-
bindings << eval_value_opt(opts[:value])
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
identifiers_cql = "#{identifiers.join(', ')}"
|
62
|
-
terms_cql = Array.new(identifiers.count){"?"}.join(", ")
|
63
|
-
|
64
|
-
[identifiers_cql, terms_cql , bindings]
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
@@ -1,60 +0,0 @@
|
|
1
|
-
require_relative 'relations'
|
2
|
-
|
3
|
-
module Cassie::Queries::Statement
|
4
|
-
module Deleting
|
5
|
-
extend ::ActiveSupport::Concern
|
6
|
-
|
7
|
-
module ClassMethods
|
8
|
-
#TODO: accept block to add specific selectors and aliases
|
9
|
-
# select :table do |t|
|
10
|
-
# t.id
|
11
|
-
# t.name as: :username
|
12
|
-
# end
|
13
|
-
def delete(table)
|
14
|
-
include Relations
|
15
|
-
|
16
|
-
self.table = table
|
17
|
-
self.identifier = :delete
|
18
|
-
|
19
|
-
yield(self) if block_given?
|
20
|
-
end
|
21
|
-
|
22
|
-
# TODO rename to identifiers and extract
|
23
|
-
def selectors
|
24
|
-
@selectors ||= []
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def delete(opts={})
|
29
|
-
execute
|
30
|
-
execution_successful?
|
31
|
-
end
|
32
|
-
|
33
|
-
protected
|
34
|
-
|
35
|
-
def build_delete_cql_and_bindings
|
36
|
-
where_str, bindings = build_where_and_bindings
|
37
|
-
|
38
|
-
cql = %(
|
39
|
-
DELETE #{build_delete_clause}
|
40
|
-
FROM #{table}
|
41
|
-
#{where_str}
|
42
|
-
).squish + ";"
|
43
|
-
|
44
|
-
[cql, bindings]
|
45
|
-
end
|
46
|
-
|
47
|
-
# a select clause is built up of selectors
|
48
|
-
def selectors
|
49
|
-
self.class.selectors
|
50
|
-
end
|
51
|
-
|
52
|
-
def build_delete_clause
|
53
|
-
str = if selectors.empty?
|
54
|
-
''
|
55
|
-
else
|
56
|
-
selectors.join(', ')
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
require_relative 'relation'
|
2
|
-
require_relative 'loading'
|
3
|
-
|
4
|
-
class Cassie::Queries::RecordNotFound < StandardError; end
|
5
|
-
|
6
|
-
module Cassie::Queries::Statement
|
7
|
-
module Fetching
|
8
|
-
extend ActiveSupport::Concern
|
9
|
-
|
10
|
-
included do
|
11
|
-
include Loading
|
12
|
-
end
|
13
|
-
|
14
|
-
# Returns array of rows or empty array
|
15
|
-
#
|
16
|
-
# query.fetch(id: 1)
|
17
|
-
# => [{id: 1, name: 'eprothro'}]
|
18
|
-
def fetch(args={})
|
19
|
-
args.each do |k, v|
|
20
|
-
setter = "#{k}="
|
21
|
-
send(setter, v) if respond_to? setter
|
22
|
-
end
|
23
|
-
|
24
|
-
execute
|
25
|
-
result.rows
|
26
|
-
end
|
27
|
-
|
28
|
-
# Returns first result or nil
|
29
|
-
#
|
30
|
-
# query.find(id: 1)
|
31
|
-
# => {id: 1, name: 'eprothro'}
|
32
|
-
#
|
33
|
-
# query.find(id: 2)
|
34
|
-
# => nil
|
35
|
-
def find(args={})
|
36
|
-
old_limit = defined?(@limit) ? @limit : nil
|
37
|
-
self.limit = 1
|
38
|
-
|
39
|
-
fetch.first
|
40
|
-
ensure
|
41
|
-
self.limit = old_limit
|
42
|
-
end
|
43
|
-
|
44
|
-
# Returns first result or raises RecordNotFound
|
45
|
-
#
|
46
|
-
# query.find!(id: 1)
|
47
|
-
# => {id: 1, name: 'eprothro'}
|
48
|
-
#
|
49
|
-
# query.find!(id: 2)
|
50
|
-
# RecordNotFound: RecordNotFound
|
51
|
-
def find!(args={})
|
52
|
-
find || raise(Cassie::Queries::RecordNotFound)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
require_relative 'assignments'
|
2
|
-
|
3
|
-
module Cassie::Queries::Statement
|
4
|
-
module Inserting
|
5
|
-
extend ::ActiveSupport::Concern
|
6
|
-
|
7
|
-
module ClassMethods
|
8
|
-
def insert(table)
|
9
|
-
include Assignments
|
10
|
-
|
11
|
-
self.table = table
|
12
|
-
self.identifier = :insert
|
13
|
-
|
14
|
-
yield(self) if block_given?
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def insert(opts={})
|
19
|
-
execute
|
20
|
-
execution_successful?
|
21
|
-
end
|
22
|
-
|
23
|
-
protected
|
24
|
-
|
25
|
-
def build_insert_cql_and_bindings
|
26
|
-
identifiers_str, terms_str, bindings = build_insert_and_bindings
|
27
|
-
|
28
|
-
cql = %(
|
29
|
-
INSERT INTO #{table}
|
30
|
-
(#{identifiers_str})
|
31
|
-
VALUES (#{terms_str})
|
32
|
-
).squish + ";"
|
33
|
-
|
34
|
-
[cql, bindings]
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
module Cassie::Queries::Statement
|
2
|
-
module Limiting
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
included do
|
6
|
-
attr_accessor :limit
|
7
|
-
|
8
|
-
class << self
|
9
|
-
attr_accessor :limit
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def limit
|
14
|
-
@limit || self.class.limit
|
15
|
-
end
|
16
|
-
|
17
|
-
protected
|
18
|
-
|
19
|
-
def build_limit_str
|
20
|
-
return "" if limit.nil?
|
21
|
-
|
22
|
-
"LIMIT #{limit}"
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
module Cassie::Queries::Statement
|
2
|
-
module Loading
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
def fetch(args={})
|
6
|
-
rows = super(args)
|
7
|
-
rows.map {|r| build_resource(r) }
|
8
|
-
end
|
9
|
-
|
10
|
-
# When class doesn't override
|
11
|
-
# simply return a struct with the row data
|
12
|
-
def build_resource(row)
|
13
|
-
Struct.new(*row.keys).new(*row.values)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
module Cassie::Queries::Statement
|
2
|
-
module Mapping
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
MAPPED_METHODS = [:insert, :update, :delete].freeze
|
6
|
-
|
7
|
-
included do
|
8
|
-
MAPPED_METHODS.each do |method|
|
9
|
-
next unless method_defined?(method)
|
10
|
-
|
11
|
-
define_method(method) do |resource=nil, opts={}|
|
12
|
-
return super(opts) if _resource.nil? && resource.nil?
|
13
|
-
|
14
|
-
self._resource = resource
|
15
|
-
|
16
|
-
if super(opts)
|
17
|
-
_resource
|
18
|
-
else
|
19
|
-
false
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
module ClassMethods
|
26
|
-
def map_from(resource_name)
|
27
|
-
attr_accessor resource_name
|
28
|
-
|
29
|
-
define_method "_resource" do
|
30
|
-
send resource_name
|
31
|
-
end
|
32
|
-
|
33
|
-
define_method "_resource=" do |val|
|
34
|
-
send("#{resource_name}=", val)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
protected
|
39
|
-
|
40
|
-
def define_term_methods(field)
|
41
|
-
getter = field
|
42
|
-
setter = "#{field}="
|
43
|
-
|
44
|
-
if method_defined?(getter) || method_defined?(setter)
|
45
|
-
raise "accessor or getter already defined for #{field}. Fix the collisions by using the `:value` option."
|
46
|
-
else
|
47
|
-
# Order of prefrence for finding term value
|
48
|
-
# 1. overriden getter instance method
|
49
|
-
# 2. value set by setter instance method
|
50
|
-
# 3. (Eventually) Mapping getter instance method
|
51
|
-
# 4. instance resource getter instance method
|
52
|
-
define_method getter do
|
53
|
-
if instance_variable_defined?("@#{field}")
|
54
|
-
return instance_variable_get("@#{field}")
|
55
|
-
end
|
56
|
-
_resource.send(field) if(_resource && _resource.respond_to?(field))
|
57
|
-
end
|
58
|
-
|
59
|
-
define_method setter do |val|
|
60
|
-
instance_variable_set("@#{field}", val)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
module Cassie::Queries::Statement
|
2
|
-
module Preparation
|
3
|
-
class Cache
|
4
|
-
attr_reader :data
|
5
|
-
|
6
|
-
def initialize
|
7
|
-
clear
|
8
|
-
@monitor = Monitor.new
|
9
|
-
end
|
10
|
-
|
11
|
-
def write(key, value)
|
12
|
-
synchronize do
|
13
|
-
@data[key] = value
|
14
|
-
end
|
15
|
-
end
|
16
|
-
def read(key)
|
17
|
-
synchronize do
|
18
|
-
data[key]
|
19
|
-
end
|
20
|
-
end
|
21
|
-
def fetch(key)
|
22
|
-
return read(key) if data.has_key?(key)
|
23
|
-
write(key, yield) if block_given?
|
24
|
-
end
|
25
|
-
def clear
|
26
|
-
@data = {}
|
27
|
-
end
|
28
|
-
def close
|
29
|
-
clear
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def synchronize(&block)
|
35
|
-
@monitor.synchronize(&block)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.cache
|
40
|
-
@cache ||= init_cache
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.init_cache
|
44
|
-
previous_cache = defined?(@cache) ? @cache : nil
|
45
|
-
|
46
|
-
#TODO: research why memory story is blowing up when
|
47
|
-
# serializing the Cassandra prepared statement result
|
48
|
-
# @cache = ActiveSupport::Cache::MemoryStore.new
|
49
|
-
@cache = Cache.new
|
50
|
-
|
51
|
-
previous_cache.close if previous_cache
|
52
|
-
@cache
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
@@ -1,47 +0,0 @@
|
|
1
|
-
require_relative 'preparation/cache'
|
2
|
-
|
3
|
-
module Cassie::Queries::Statement
|
4
|
-
module Preparation
|
5
|
-
extend ::ActiveSupport::Concern
|
6
|
-
|
7
|
-
included do
|
8
|
-
class << self
|
9
|
-
attr_accessor :prepare
|
10
|
-
end
|
11
|
-
self.prepare = true
|
12
|
-
end
|
13
|
-
|
14
|
-
module ClassMethods
|
15
|
-
def inherited(subclass)
|
16
|
-
subclass.prepare = prepare
|
17
|
-
super
|
18
|
-
end
|
19
|
-
|
20
|
-
def prepare?
|
21
|
-
!!prepare
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def statement
|
26
|
-
statement = super
|
27
|
-
|
28
|
-
if self.class.prepare?
|
29
|
-
key = statement.cql if statement.respond_to?(:cql)
|
30
|
-
key ||= statement.to_s
|
31
|
-
|
32
|
-
unbound = statement_cache.fetch(key) do
|
33
|
-
session.prepare(statement)
|
34
|
-
end
|
35
|
-
unbound.bind(statement.params)
|
36
|
-
else
|
37
|
-
statement
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
|
43
|
-
def statement_cache
|
44
|
-
Cassie::Queries::Statement::Preparation.cache
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,59 +0,0 @@
|
|
1
|
-
module Cassie::Queries::Statement
|
2
|
-
#
|
3
|
-
#
|
4
|
-
# relation "username = ?", value: :username
|
5
|
-
# relation :username, :eq
|
6
|
-
# relation :username, :eq, value: :method
|
7
|
-
# relation :phone, :in
|
8
|
-
class Relation
|
9
|
-
# https://cassandra.apache.org/doc/cql3/CQL.html#selectStmt
|
10
|
-
|
11
|
-
OPERATIONS = {
|
12
|
-
eq: "=",
|
13
|
-
lt: "<",
|
14
|
-
lteq: "<=",
|
15
|
-
gt: ">",
|
16
|
-
gteq: ">=",
|
17
|
-
contains: "CONTAINS",
|
18
|
-
contains_key: "CONTAINS KEY",
|
19
|
-
}
|
20
|
-
|
21
|
-
attr_reader :identifier,
|
22
|
-
:op_type
|
23
|
-
|
24
|
-
def initialize(identifier, op_type, opts={})
|
25
|
-
if Hash === op_type
|
26
|
-
# custom relation is being defined:
|
27
|
-
# `relation "username = ?", value: :username`
|
28
|
-
|
29
|
-
# swap the 2nd arg that sucked in options hash
|
30
|
-
opts.merge!(op_type)
|
31
|
-
|
32
|
-
@cql = identifier
|
33
|
-
@custom = true
|
34
|
-
else
|
35
|
-
@identifier = identifier
|
36
|
-
@op_type = op_type.to_sym
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def custom?
|
41
|
-
!!@custom
|
42
|
-
end
|
43
|
-
|
44
|
-
def to_cql
|
45
|
-
cql
|
46
|
-
end
|
47
|
-
|
48
|
-
protected
|
49
|
-
|
50
|
-
def cql
|
51
|
-
# we always generate bound statements
|
52
|
-
@cql ||= "#{identifier} #{OPERATIONS[op_type]} ?"
|
53
|
-
end
|
54
|
-
|
55
|
-
def op_type
|
56
|
-
@op_type
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
@@ -1,64 +0,0 @@
|
|
1
|
-
require_relative 'relation'
|
2
|
-
|
3
|
-
module Cassie::Queries::Statement
|
4
|
-
module Relations
|
5
|
-
extend ActiveSupport::Concern
|
6
|
-
|
7
|
-
module ClassMethods
|
8
|
-
# where :username, :eq, value: :method
|
9
|
-
# where :phone, :in
|
10
|
-
# were "username = ?", value: :username
|
11
|
-
def where(identifier, op, opts={})
|
12
|
-
relation = Relation.new(identifier, op, opts)
|
13
|
-
|
14
|
-
opts[:value] ||= identifier.to_sym
|
15
|
-
|
16
|
-
if Symbol === opts[:value]
|
17
|
-
define_term_methods(opts[:value])
|
18
|
-
end
|
19
|
-
|
20
|
-
relations[relation] = opts
|
21
|
-
end
|
22
|
-
|
23
|
-
# a where clause is built up of multiple 'relations'
|
24
|
-
def relations
|
25
|
-
@relations ||= {}
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
def define_term_methods(name)
|
31
|
-
#TODO: this should probably only raise
|
32
|
-
# if value option was nil and we
|
33
|
-
# are implicilty creating getter/setters.
|
34
|
-
if method_defined?(name) || method_defined?("#{name}=")
|
35
|
-
raise "accessor or getter already defined for #{name}. Fix the collions by using the `:value` option."
|
36
|
-
else
|
37
|
-
attr_accessor name
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
# a where clause is built up of multiple 'relations'
|
43
|
-
def relations
|
44
|
-
self.class.relations
|
45
|
-
end
|
46
|
-
|
47
|
-
def build_where_and_bindings
|
48
|
-
cql = ""
|
49
|
-
bindings = []
|
50
|
-
relation_strings = []
|
51
|
-
|
52
|
-
relations.each do |r, opts|
|
53
|
-
if eval_if_opt?(opts[:if])
|
54
|
-
relation_strings << r.to_cql
|
55
|
-
bindings << eval_value_opt(opts[:value])
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
cql = "WHERE #{relation_strings.join(' AND ')}" unless bindings.empty?
|
60
|
-
|
61
|
-
[cql , bindings]
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
@@ -1,63 +0,0 @@
|
|
1
|
-
require_relative 'relations'
|
2
|
-
require_relative 'limiting'
|
3
|
-
require_relative 'ordering'
|
4
|
-
require_relative 'fetching'
|
5
|
-
|
6
|
-
module Cassie::Queries::Statement
|
7
|
-
module Selection
|
8
|
-
extend ::ActiveSupport::Concern
|
9
|
-
|
10
|
-
module ClassMethods
|
11
|
-
#TODO: accept block to add specific selectors and aliases
|
12
|
-
# select :table do |t|
|
13
|
-
# t.id
|
14
|
-
# t.name as: :username
|
15
|
-
# end
|
16
|
-
def select(table)
|
17
|
-
include Relations
|
18
|
-
include Limiting
|
19
|
-
include Ordering
|
20
|
-
include Fetching
|
21
|
-
|
22
|
-
self.table = table
|
23
|
-
self.identifier = :select
|
24
|
-
|
25
|
-
yield(self) if block_given?
|
26
|
-
end
|
27
|
-
|
28
|
-
# a select clause is built up of selectors
|
29
|
-
def selectors
|
30
|
-
@selectors ||= []
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
protected
|
35
|
-
|
36
|
-
def build_select_cql_and_bindings
|
37
|
-
where_str, bindings = build_where_and_bindings
|
38
|
-
|
39
|
-
cql = %(
|
40
|
-
SELECT #{build_select_clause}
|
41
|
-
FROM #{table}
|
42
|
-
#{where_str}
|
43
|
-
#{build_order_str}
|
44
|
-
#{build_limit_str}
|
45
|
-
).squish + ";"
|
46
|
-
|
47
|
-
[cql, bindings]
|
48
|
-
end
|
49
|
-
|
50
|
-
# a select clause is built up of selectors
|
51
|
-
def selectors
|
52
|
-
self.class.selectors
|
53
|
-
end
|
54
|
-
|
55
|
-
def build_select_clause
|
56
|
-
str = if selectors.empty?
|
57
|
-
'*'
|
58
|
-
else
|
59
|
-
selectors.join(', ')
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
require_relative 'assignments'
|
2
|
-
|
3
|
-
module Cassie::Queries::Statement
|
4
|
-
module Updating
|
5
|
-
extend ::ActiveSupport::Concern
|
6
|
-
|
7
|
-
module ClassMethods
|
8
|
-
def update(table)
|
9
|
-
include Relations
|
10
|
-
include Assignments
|
11
|
-
|
12
|
-
self.table = table
|
13
|
-
self.identifier = :update
|
14
|
-
|
15
|
-
yield(self) if block_given?
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def update(opts={})
|
20
|
-
execute
|
21
|
-
execution_successful?
|
22
|
-
end
|
23
|
-
|
24
|
-
protected
|
25
|
-
|
26
|
-
def build_update_cql_and_bindings
|
27
|
-
assignment_str, update_bindings = build_update_and_bindings
|
28
|
-
where_str, where_bindings = build_where_and_bindings
|
29
|
-
|
30
|
-
cql = %(
|
31
|
-
UPDATE #{table}
|
32
|
-
SET #{assignment_str}
|
33
|
-
#{where_str}
|
34
|
-
).squish + ";"
|
35
|
-
|
36
|
-
[cql, update_bindings + where_bindings]
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,99 +0,0 @@
|
|
1
|
-
require 'active_support/core_ext/string/filters'
|
2
|
-
require_relative 'statement/preparation'
|
3
|
-
require_relative 'statement/selection'
|
4
|
-
require_relative 'statement/deleting'
|
5
|
-
require_relative 'statement/updating'
|
6
|
-
require_relative 'statement/inserting'
|
7
|
-
|
8
|
-
|
9
|
-
module Cassie::Queries
|
10
|
-
module Statement
|
11
|
-
# https://cassandra.apache.org/doc/cql3/CQL.html#selectStmt
|
12
|
-
extend ::ActiveSupport::Concern
|
13
|
-
|
14
|
-
included do
|
15
|
-
include Preparation
|
16
|
-
include Selection
|
17
|
-
include Deleting
|
18
|
-
include Updating
|
19
|
-
include Inserting
|
20
|
-
|
21
|
-
attr_reader :result
|
22
|
-
|
23
|
-
class << self
|
24
|
-
attr_accessor :table
|
25
|
-
attr_accessor :identifier
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def table
|
30
|
-
self.class.table
|
31
|
-
end
|
32
|
-
|
33
|
-
# Executes the statment, populates result
|
34
|
-
# returns true or false indicating a successful execution or not
|
35
|
-
def execute
|
36
|
-
@result = session.execute(statement)
|
37
|
-
execution_successful?
|
38
|
-
end
|
39
|
-
|
40
|
-
# returns a CQL string, or a Cassandra::Statement
|
41
|
-
# that is ready for execution
|
42
|
-
def statement
|
43
|
-
Cassandra::Statements::Simple.new(*build_cql_and_bindings)
|
44
|
-
end
|
45
|
-
|
46
|
-
protected
|
47
|
-
|
48
|
-
def build_cql_and_bindings
|
49
|
-
if identifier
|
50
|
-
send "build_#{identifier}_cql_and_bindings"
|
51
|
-
else
|
52
|
-
[cql, bindings]
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def execution_successful?
|
57
|
-
#TODO: rethink this, it knows too much
|
58
|
-
raise "execution not complete, no results to parse" unless result
|
59
|
-
|
60
|
-
# empty select
|
61
|
-
return true if result.empty?
|
62
|
-
|
63
|
-
# failed upsert
|
64
|
-
return false if (!result.rows.first["[applied]"].nil?) && (result.rows.first["[applied]"] == false)
|
65
|
-
|
66
|
-
true
|
67
|
-
end
|
68
|
-
|
69
|
-
private
|
70
|
-
|
71
|
-
def identifier
|
72
|
-
self.class.identifier
|
73
|
-
end
|
74
|
-
|
75
|
-
def eval_if_opt?(value)
|
76
|
-
case value
|
77
|
-
when nil
|
78
|
-
true # if is true by default
|
79
|
-
when Symbol
|
80
|
-
!!send(value)
|
81
|
-
when String
|
82
|
-
!!eval(value)
|
83
|
-
else
|
84
|
-
!!value
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def eval_value_opt(value)
|
89
|
-
case value
|
90
|
-
when Symbol
|
91
|
-
send(value)
|
92
|
-
when String
|
93
|
-
eval(value)
|
94
|
-
else
|
95
|
-
value
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
data/lib/cassie/query.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
module Cassie
|
2
|
-
require 'cassandra'
|
3
|
-
require_relative 'queries/session'
|
4
|
-
require_relative 'queries/statement'
|
5
|
-
require_relative 'queries/pagination'
|
6
|
-
require_relative 'queries/instrumentation'
|
7
|
-
require_relative 'queries/logging'
|
8
|
-
|
9
|
-
class Query
|
10
|
-
include Queries::Session
|
11
|
-
include Queries::Statement
|
12
|
-
include Queries::Pagination
|
13
|
-
include Queries::Instrumentation
|
14
|
-
include Queries::Logging
|
15
|
-
|
16
|
-
def initialize(*args)
|
17
|
-
value = super(*args)
|
18
|
-
after_initialize(*args)
|
19
|
-
value
|
20
|
-
end
|
21
|
-
|
22
|
-
def after_initialize(*args)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
data/lib/cassie-queries.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
# Active Support used for
|
2
|
-
# * include convenience via ActiveSupport::Concern
|
3
|
-
# * string extensions
|
4
|
-
# * notification pub/sub
|
5
|
-
# * log formatting
|
6
|
-
#
|
7
|
-
# We require/autoload extensions only as needed,
|
8
|
-
# this base require has almost no overhead
|
9
|
-
#
|
10
|
-
# http://guides.rubyonrails.org/active_support_core_extensions.html
|
11
|
-
require 'active_support'
|
12
|
-
|
13
|
-
# Use cassie directory instead of cassie-queries
|
14
|
-
# to allow sharing of cassie module with other libraries
|
15
|
-
# but maintain folder/file/module/class naming conventions
|
16
|
-
require_relative 'cassie/query'
|