cassie-queries 0.0.1.a3 → 0.0.1.a4

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 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