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.
112 113 114 115 116 117 118 |
# File 'lib/praxis-mapper/query/base.rb', line 112 def where(value=nil) if value @where = value else return @where end end |
Instance Method Details
#_execute ⇒ Object
Subclasses Must Implement
242 243 244 |
# File 'lib/praxis-mapper/query/base.rb', line 242 def _execute raise "subclass responsibility" end |
#_multi_get(identity, values) ⇒ Object
Subclasses Must Implement
237 238 239 |
# File 'lib/praxis-mapper/query/base.rb', line 237 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
161 162 163 164 165 166 167 168 169 |
# File 'lib/praxis-mapper/query/base.rb', line 161 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 102 103 104 105 |
# File 'lib/praxis-mapper/query/base.rb', line 97 def default_select model.identities.each_with_object({}).each do |identity, hash| if identity.is_a? Array identity.each { |id| hash[id] = nil } else hash[identity] = nil end end end |
#describe ⇒ Object
Subclasses Must Implement the sql or “sql-like” representation of the query
248 249 250 |
# File 'lib/praxis-mapper/query/base.rb', line 248 def describe raise "subclass responsibility" end |
#execute ⇒ Array
Executes assembled read query and returns all matching records.
216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/praxis-mapper/query/base.rb', line 216 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.
125 126 127 128 129 130 131 |
# File 'lib/praxis-mapper/query/base.rb', line 125 def limit(value=nil) if value @limit = value else return @limit end end |
#load(*values, &block) ⇒ Object
148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/praxis-mapper/query/base.rb', line 148 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.
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/praxis-mapper/query/base.rb', line 188 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
228 229 230 231 232 233 234 |
# File 'lib/praxis-mapper/query/base.rb', line 228 def to_records(rows) rows.collect do |row| m = model.new(row) m._query = self m end end |
#track(*values, &block) ⇒ Object
134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/praxis-mapper/query/base.rb', line 134 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.
173 174 175 176 177 178 179 |
# File 'lib/praxis-mapper/query/base.rb', line 173 def tracked_associations track.collect do |(name, _)| model.associations.fetch(name) do raise "association #{name.inspect} not found for #{model}" end end.uniq end |