Class: Praxis::Mapper::Query::Base
- Inherits:
-
Object
- Object
- Praxis::Mapper::Query::Base
- Defined in:
- lib/praxis-mapper/query/base.rb
Overview
Abstract base class for assembling read queries for a data store. May be implemented for SQL, CQL, etc. Collects query statistics.
Direct Known Subclasses
Constant Summary collapse
- MULTI_GET_BATCH_SIZE =
4_096
Instance Attribute Summary collapse
-
#contexts ⇒ Object
readonly
Returns the value of attribute contexts.
-
#identity_map ⇒ Object
readonly
Returns the value of attribute identity_map.
-
#model ⇒ Object
readonly
Returns the value of attribute model.
-
#statistics ⇒ Object
readonly
Returns the value of attribute statistics.
-
#where(value = nil) ⇒ Object
Gets or sets an SQL-like ‘WHERE’ clause to this query.
Instance Method Summary collapse
-
#_execute ⇒ Object
Subclasses Must Implement.
-
#_multi_get(identity, values) ⇒ Object
Subclasses Must Implement.
- #apply_selector(selector) ⇒ Object
-
#connection ⇒ Object
Handle to configured data store.
- #context(name = nil) ⇒ Object
- #default_select ⇒ Object
-
#describe ⇒ Object
Subclasses Must Implement the sql or “sql-like” representation of the query.
-
#execute ⇒ Array
Executes assembled read query and returns all matching records.
-
#initialize(identity_map, model, &block) ⇒ Base
constructor
Sets up a read query.
-
#limit(value = nil) ⇒ Object
Gets or sets an SQL-like ‘LIMIT’ clause to this query.
- #load(*values, &block) ⇒ Object
-
#multi_get(identity, values, select: nil, raw: false) ⇒ Array
Executes multi-get read query and returns all matching records.
-
#select(*fields) ⇒ Hash
Gets or sets an SQL-like ‘SELECT’ clause to this query.
- #to_records(rows) ⇒ Object
- #track(*values, &block) ⇒ Object
-
#tracked_associations ⇒ Array
A list of associated models.
Constructor Details
#initialize(identity_map, model, &block) ⇒ Base
Sets up a read query.
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/praxis-mapper/query/base.rb', line 20 def initialize(identity_map, model, &block) @identity_map = identity_map @model = model @select = nil @where = nil @limit = nil @track = Set.new @load = Set.new @contexts = Set.new @statistics = Hash.new(0) # general-purpose hash if (selector = identity_map.selectors[model]) self.apply_selector(selector) end if block_given? self.instance_eval(&block) end end |
Instance Attribute Details
#contexts ⇒ Object (readonly)
Returns the value of attribute contexts.
12 13 14 |
# File 'lib/praxis-mapper/query/base.rb', line 12 def contexts @contexts end |
#identity_map ⇒ Object (readonly)
Returns the value of attribute identity_map.
12 13 14 |
# File 'lib/praxis-mapper/query/base.rb', line 12 def identity_map @identity_map end |
#model ⇒ Object (readonly)
Returns the value of attribute model.
12 13 14 |
# File 'lib/praxis-mapper/query/base.rb', line 12 def model @model end |
#statistics ⇒ Object (readonly)
Returns the value of attribute statistics.
12 13 14 |
# File 'lib/praxis-mapper/query/base.rb', line 12 def statistics @statistics end |
#where(value = nil) ⇒ Object
Gets or sets an SQL-like ‘WHERE’ clause to this query.
108 109 110 111 112 113 114 |
# File 'lib/praxis-mapper/query/base.rb', line 108 def where(value=nil) if value @where = value else return @where end end |
Instance Method Details
#_execute ⇒ Object
Subclasses Must Implement
238 239 240 |
# File 'lib/praxis-mapper/query/base.rb', line 238 def _execute raise "subclass responsibility" end |
#_multi_get(identity, values) ⇒ Object
Subclasses Must Implement
233 234 235 |
# File 'lib/praxis-mapper/query/base.rb', line 233 def _multi_get(identity, values) raise "subclass responsibility" end |
#apply_selector(selector) ⇒ Object
46 47 48 49 50 51 52 53 54 |
# File 'lib/praxis-mapper/query/base.rb', line 46 def apply_selector(selector) if selector[:select] self.select(*selector[:select]) end if selector[:track] self.track(*selector[:track]) end end |
#connection ⇒ Object
Returns handle to configured data store.
57 58 59 |
# File 'lib/praxis-mapper/query/base.rb', line 57 def connection identity_map.connection(model.repository_name) end |
#context(name = nil) ⇒ Object
157 158 159 160 161 162 163 164 165 |
# File 'lib/praxis-mapper/query/base.rb', line 157 def context(name=nil) @contexts << name spec = model.contexts.fetch(name) do raise "context #{name.inspect} not found for #{model}" end select(*spec[:select]) track(*spec[:track]) end |
#default_select ⇒ Object
97 98 99 100 101 |
# File 'lib/praxis-mapper/query/base.rb', line 97 def default_select model.identities.each_with_object({}).each do |identity, hash| hash[identity] = nil end end |
#describe ⇒ Object
Subclasses Must Implement the sql or “sql-like” representation of the query
244 245 246 |
# File 'lib/praxis-mapper/query/base.rb', line 244 def describe raise "subclass responsibility" end |
#execute ⇒ Array
Executes assembled read query and returns all matching records.
212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/praxis-mapper/query/base.rb', line 212 def execute if self.frozen? raise TypeError.new "can not reuse a frozen query" end statistics[:execute] += 1 rows = _execute statistics[:records_loaded] += rows.size to_records(rows) end |
#limit(value = nil) ⇒ Object
Gets or sets an SQL-like ‘LIMIT’ clause to this query.
121 122 123 124 125 126 127 |
# File 'lib/praxis-mapper/query/base.rb', line 121 def limit(value=nil) if value @limit = value else return @limit end end |
#load(*values, &block) ⇒ Object
144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/praxis-mapper/query/base.rb', line 144 def load(*values, &block) if values.any? if block_given? raise "block and multiple values not supported" if values.size > 1 @load << [values.first, block] else @load.merge(values) end else return @load end end |
#multi_get(identity, values, select: nil, raw: false) ⇒ Array
Executes multi-get read query and returns all matching records.
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/praxis-mapper/query/base.rb', line 184 def multi_get(identity, values, select: nil, raw: false) if self.frozen? raise TypeError.new "can not reuse a frozen query" end statistics[:multi_get] += 1 rows = [] original_select = @select self.select(*select.flatten.uniq) if select values.each_slice(MULTI_GET_BATCH_SIZE) do |batch| rows += _multi_get(identity, batch) end statistics[:records_loaded] += rows.size return rows if raw to_records(rows) ensure @select = original_select unless self.frozen? end |
#select(*fields) ⇒ Hash
Gets or sets an SQL-like ‘SELECT’ clause to this query. TODO: fix any specs or code that uses alias
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/praxis-mapper/query/base.rb', line 68 def select(*fields) if fields.any? return @select if @select == true if @select.nil? @select = default_select end fields.each do |field| case field when Symbol, String if field == :* || field == "*" @select = true break else @select[field] = nil end when Hash field.each do |alias_name, column_name| @select[alias_name] = column_name end else raise "unknown field type: #{field.class.name}" end end else return @select end end |
#to_records(rows) ⇒ Object
224 225 226 227 228 229 230 |
# File 'lib/praxis-mapper/query/base.rb', line 224 def to_records(rows) rows.collect do |row| m = model.new(row) m._query = self m end end |
#track(*values, &block) ⇒ Object
130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/praxis-mapper/query/base.rb', line 130 def track(*values, &block) if values.any? if block_given? raise "block and multiple values not supported" if values.size > 1 @track << [values.first, block] else @track.merge(values) end else return @track end end |
#tracked_associations ⇒ Array
Returns a list of associated models.
169 170 171 172 173 174 175 |
# File 'lib/praxis-mapper/query/base.rb', line 169 def tracked_associations track.collect do |(name, _)| model.associations.fetch(name) do raise "association #{name.inspect} not found for #{model}" end end.uniq end |