Class: Hecks::Adapters::SqliteProjection

Inherits:
Sqlite
  • Object
show all
Defined in:
lib/hecks/adapters/driven/sqlite/projection.rb

Overview

Rebuilds a read store from the authoritative journal, entry by entry. A value object is written as its JSON object and a reference as the bare id it holds — the same shapes the command path writes, so there is no second representation to accept here any more.

Constant Summary

Constants inherited from Sqlite

Hecks::Adapters::Sqlite::SQL_TYPES

Constants included from SqlQueryBuilder

Hecks::Adapters::SqlQueryBuilder::COMPARATORS

Instance Attribute Summary

Attributes inherited from Sqlite

#aggregate, #path

Instance Method Summary collapse

Methods inherited from Sqlite

#all, #append, #atomic_put, #count, #delete, #delete_saga, #each_saga, #entries, #events, #find, #initialize, #persistence_capabilities, #record_event, #reset!, #save, #save_saga, #table

Methods included from SqlQueryBuilder

#query

Constructor Details

This class inherits a constructor from Hecks::Adapters::Sqlite

Instance Method Details

#project(entry) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
# File 'lib/hecks/adapters/driven/sqlite/projection.rb', line 17

def project(entry)
  return @db.execute("DELETE FROM #{quoted_table} WHERE id = ?", [entry.id]) if entry.delete?

  columns = (["id"] + persisted_fields.map { |field| field[:name].to_s }).map { |column| quote_ident(column) }
  values  = [entry.id.to_s] + persisted_fields.map { |field| encode_field(field, entry.state[field[:name]]) }
  @db.execute(
    "INSERT OR REPLACE INTO #{quoted_table} (#{columns.join(', ')}) VALUES (#{Array.new(columns.size,
                                                                                        '?').join(', ')})", values
  )
  entry
end

#query_read_model(_domain, model, args, bluebook = nil) ⇒ Object

Execute a declared read model against the projected aggregate-head tables. The report shape is assembled from SQL-selected rows, rather than scanning repositories and matching references in Ruby.

Raises:

  • (ArgumentError)


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/hecks/adapters/driven/sqlite/projection.rb', line 32

def query_read_model(_domain, model, args, bluebook = nil)
  raise ArgumentError, "projection query needs its domain bluebook" unless bluebook

  # The REFERENCE's own shape, read the same way ReadModelInterpreter
  # reads it — not the identity unwrap, which is gone : an identity is
  # declared as a path and followed.
  reference_id = args.fetch(model.reference_name).to_s
  eligible = model.filtered_head_name
  reports = {}
  model.aggregate_heads.each do |head|
    aggregate = bluebook.aggregate(head[:aggregate])
    rows = if head[:aggregate] == model.reference_target
             [select_projected(aggregate, reference_id)].compact
           else
             select_related(aggregate, model.reference_target, reference_id)
           end
    rows = Ports::Query::InMemory.execute(rows, model, args) if head[:as] == eligible
    reports[head[:as]] = if head[:many]
                           rows.map { |row| Runtime::Value.materialize(row.to_h) }
                         else
                           rows.first && Runtime::Value.materialize(rows.first.to_h)
                         end
  end
  [reports]
end