cassie-queries 0.0.1.a3 → 0.0.1.a4

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: cb242e7d39178042db018afd756662c8fad3c97f
4
- data.tar.gz: 635694c6fa09a3c33a4344a510a168f30f7395ff
3
+ metadata.gz: 43d357d81ed74c4e0e24a0536842f3cb0c135681
4
+ data.tar.gz: 246a0d7be210bbdea3bc1c1ce3f70fdd445d7eb7
5
5
  SHA512:
6
- metadata.gz: 2dcaa13edba2a7d1df4a6775efdf75671fc7782e2e8f3358748e2356acd17200098d6eeda84cb2d2b8774a4e15727d2220ea7b4397859a611713b16bc5a3af53
7
- data.tar.gz: 6ee8cb5798723ecb6ca88133e07cdd7088bb6ea3558635db69b615e11644ba1c97a7a03b5d8e6f93422d198936d0d70d68d511f2ec1f2afda84ff12f29c5de4d
6
+ metadata.gz: 4561e775d74984005a279c954b4ad638da526830b6a1ab52a82f17def1208604180b168b2011b9baed3e993e9e0a0e5e730e88e70698604b8a439c91781541a1
7
+ data.tar.gz: 4922dbc93622b6cbc63bf89643e149165fd0484b91b8b617b61acde5291b02f8dc17dcff3e8916ffc57bcc9241e949f00ef8ecb0239d0603faf6101a0db8d76f
@@ -9,7 +9,8 @@ module Cassie::Queries
9
9
  def instrument #:nodoc:
10
10
  instrumenter.instrument("cql.execute") do |payload|
11
11
  execution_val = yield # execution populates #result
12
- payload[:execution_info] = result.try(:execution_info)
12
+
13
+ payload[:execution_info] = result.execution_info if result.respond_to?(:execution_info)
13
14
  execution_val
14
15
  end
15
16
  end
@@ -19,10 +19,14 @@ module Cassie::Queries::Logging
19
19
  end
20
20
 
21
21
  def statement
22
- statement = execution_info.statement
23
- str = statement.cql
24
- str += " [#{statement.params}]" if statement.respond_to? :params
25
- str
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
26
30
  end
27
31
 
28
32
  def traced?
@@ -10,7 +10,7 @@ module Cassie::Queries
10
10
  end
11
11
 
12
12
  def self.init_logger(target = STDOUT)
13
- previous_logger = @logger
13
+ previous_logger = defined?(@logger) ? @logger : nil
14
14
 
15
15
  @logger = Logger.new(target)
16
16
  @logger.level = Logger::INFO
@@ -0,0 +1,15 @@
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
@@ -0,0 +1,7 @@
1
+ module Cassie::Queries::Pagination
2
+ module PageSize
3
+ def self.default
4
+ 100
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,37 @@
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
@@ -0,0 +1,36 @@
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
@@ -0,0 +1,67 @@
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
@@ -0,0 +1,60 @@
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
@@ -0,0 +1,55 @@
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
@@ -0,0 +1,37 @@
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
@@ -0,0 +1,25 @@
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
@@ -0,0 +1,16 @@
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
@@ -0,0 +1,66 @@
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
@@ -0,0 +1,11 @@
1
+ module Cassie::Queries::Statement
2
+ module Ordering
3
+ extend ActiveSupport::Concern
4
+
5
+ protected
6
+
7
+ def build_order_str
8
+ ""
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,55 @@
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
@@ -0,0 +1,47 @@
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
@@ -0,0 +1,59 @@
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
@@ -0,0 +1,64 @@
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
@@ -0,0 +1,63 @@
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
@@ -0,0 +1,39 @@
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,48 +1,60 @@
1
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
+
2
8
 
3
9
  module Cassie::Queries
4
10
  module Statement
11
+ # https://cassandra.apache.org/doc/cql3/CQL.html#selectStmt
5
12
  extend ::ActiveSupport::Concern
6
13
 
7
14
  included do
15
+ include Preparation
16
+ include Selection
17
+ include Deleting
18
+ include Updating
19
+ include Inserting
20
+
8
21
  attr_reader :result
9
- end
10
22
 
11
- module ClassMethods
12
- def cql(statement)
13
- if self.const_defined?(:STATEMENT)
14
- raise "a cql statement has already been defined and cannot be changed"
15
- else
16
- self.const_set(:STATEMENT, statement.squish)
17
- end
23
+ class << self
24
+ attr_accessor :table
25
+ attr_accessor :identifier
18
26
  end
27
+ end
19
28
 
20
- def statement
21
- self.const_get(:STATEMENT)
22
- rescue NameError
23
- end
29
+ def table
30
+ self.class.table
24
31
  end
25
32
 
26
33
  # Executes the statment, populates result
27
34
  # returns true or false indicating a successful execution or not
28
35
  def execute
29
- @result = session.execute(statement, arguments: bindings)
36
+ @result = session.execute(statement)
30
37
  execution_successful?
31
38
  end
32
39
 
40
+ # returns a CQL string, or a Cassandra::Statement
41
+ # that is ready for execution
33
42
  def statement
34
- self.class.statement
43
+ Cassandra::Statements::Simple.new(*build_cql_and_bindings)
35
44
  end
36
45
 
37
46
  protected
38
47
 
39
- def bindings
40
- []
48
+ def build_cql_and_bindings
49
+ if identifier
50
+ send "build_#{identifier}_cql_and_bindings"
51
+ else
52
+ [cql, bindings]
53
+ end
41
54
  end
42
55
 
43
- private
44
-
45
56
  def execution_successful?
57
+ #TODO: rethink this, it knows too much
46
58
  raise "execution not complete, no results to parse" unless result
47
59
 
48
60
  # empty select
@@ -53,5 +65,35 @@ module Cassie::Queries
53
65
 
54
66
  true
55
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
56
98
  end
57
99
  end
data/lib/cassie/query.rb CHANGED
@@ -2,15 +2,24 @@ module Cassie
2
2
  require 'cassandra'
3
3
  require_relative 'queries/session'
4
4
  require_relative 'queries/statement'
5
- require_relative 'queries/prepared_statement'
5
+ require_relative 'queries/pagination'
6
6
  require_relative 'queries/instrumentation'
7
7
  require_relative 'queries/logging'
8
8
 
9
9
  class Query
10
10
  include Queries::Session
11
11
  include Queries::Statement
12
- include Queries::PreparedStatement
12
+ include Queries::Pagination
13
13
  include Queries::Instrumentation
14
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
15
24
  end
16
25
  end
metadata CHANGED
@@ -1,88 +1,119 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cassie-queries
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.a3
4
+ version: 0.0.1.a4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Prothro
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-11 00:00:00.000000000 Z
11
+ date: 2015-12-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cassandra-driver
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '2.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '2.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activesupport
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '4.2'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '4.2'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: '3.4'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.4'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: byebug
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
- description: '`cassie-queries` is a lightweight interface adapter allowing easy use
70
- of the functionality provided by the `cassandra-driver`.'
69
+ - !ruby/object:Gem::Dependency
70
+ name: benchmark-ips
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: "`cassie-queries` is a lightweight interface adapter allowing easy use
84
+ of the functionality provided by the `cassandra-driver`."
71
85
  email: evan.prothro@gmail.com
72
86
  executables: []
73
87
  extensions: []
74
88
  extra_rdoc_files: []
75
89
  files:
90
+ - lib/cassie-queries.rb
76
91
  - lib/cassie/queries/instrumentation.rb
92
+ - lib/cassie/queries/logging.rb
77
93
  - lib/cassie/queries/logging/cql_execution_event.rb
78
94
  - lib/cassie/queries/logging/logger.rb
79
95
  - lib/cassie/queries/logging/subscription.rb
80
- - lib/cassie/queries/logging.rb
81
- - lib/cassie/queries/prepared_statement.rb
96
+ - lib/cassie/queries/pagination.rb
97
+ - lib/cassie/queries/pagination/cursors.rb
98
+ - lib/cassie/queries/pagination/page_size.rb
82
99
  - lib/cassie/queries/session.rb
83
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
84
116
  - lib/cassie/query.rb
85
- - lib/cassie-queries.rb
86
117
  homepage: https://github.com/eprothro/cassie-queries
87
118
  licenses:
88
119
  - MIT
@@ -93,17 +124,17 @@ require_paths:
93
124
  - lib
94
125
  required_ruby_version: !ruby/object:Gem::Requirement
95
126
  requirements:
96
- - - '>='
127
+ - - ">="
97
128
  - !ruby/object:Gem::Version
98
129
  version: '0'
99
130
  required_rubygems_version: !ruby/object:Gem::Requirement
100
131
  requirements:
101
- - - '>'
132
+ - - ">"
102
133
  - !ruby/object:Gem::Version
103
134
  version: 1.3.1
104
135
  requirements: []
105
136
  rubyforge_project:
106
- rubygems_version: 2.0.14
137
+ rubygems_version: 2.5.1
107
138
  signing_key:
108
139
  specification_version: 4
109
140
  summary: Apache Cassandra query management
@@ -1,40 +0,0 @@
1
- module Cassie::Queries
2
- module PreparedStatement
3
- extend ::ActiveSupport::Concern
4
-
5
- included do
6
- class << self
7
- attr_accessor :prepare
8
- end
9
- self.prepare = true
10
- end
11
-
12
- module ClassMethods
13
- def inherited(subclass)
14
- subclass.prepare = prepare
15
- end
16
-
17
- def prepare?
18
- !!prepare
19
- end
20
-
21
- def prepared_statement
22
- # use class instance variable to esnure only 1
23
- # statement is prepared per process
24
- # no mutex required in MRI because of GIL
25
- #
26
- # note: cassandra-driver handles the case
27
- # of executing a prepared statement
28
- # on a host where it has not been prepared
29
- # yet, by re-preparing.
30
- @prepared_statement ||= begin
31
- session.prepare(statement)
32
- end
33
- end
34
- end
35
-
36
- def statement
37
- self.class.prepare? ? self.class.prepared_statement : super
38
- end
39
- end
40
- end