Class: Mochigome::Query
- Inherits:
-
Object
- Object
- Mochigome::Query
- Defined in:
- lib/query.rb
Instance Method Summary collapse
-
#initialize(layers, options = {}) ⇒ Query
constructor
A new instance of Query.
- #run(cond = nil) ⇒ Object
Constructor Details
#initialize(layers, options = {}) ⇒ Query
Returns a new instance of Query.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/query.rb', line 3 def initialize(layers, = {}) @name = .delete(:root_name).try(:to_s) || "report" access_filter = .delete(:access_filter) || lambda {|cls| {}} aggregate_sources = .delete(:aggregate_sources) || {} @fieldsets = .delete(:fieldsets) || {} unless .empty? raise QueryError.new("Unknown options: #{.keys.inspect}") end if layers.is_a? Array layer_paths = [layers] else unless layers.is_a?(Hash) && layers.size == 1 && layers.keys.first == :report raise QueryError.new("Invalid layer tree") end layer_paths = Query.tree_root_to_leaf_paths(layers.values.first) end layer_paths = [[]] if layer_paths.empty? # Create at least one QueryLine @lines = layer_paths.map{ |path| QueryLine.new(path, access_filter) } # Given a simple array of aggregates, just apply to every point if aggregate_sources.is_a?(Array) as_hash = ActiveSupport::OrderedHash.new aggregate_sources.each do |a| layer_paths.each do |path| (0..path.size).each do |len| key = [:report] + path.take(len) as_hash[key] ||= [] as_hash[key] << a unless as_hash[key].include?(a) end end end aggregate_sources = as_hash end agg_only_lines = [] aggregate_sources.each do |path, aggs| models_path = path.drop(1) # Remove the :report symbol at the start tgt_line = @lines.find do |line| line.layer_path.take(models_path.size) == models_path end unless tgt_line raise QueryError.new("Cannot find path #{path.inspect} for agg") end aggs.each do |a| tgt_line.add_aggregate_source(models_path.size, a) if tgt_line.layer_path != models_path # FIXME Copy&paste from add_aggregate_source if a.is_a?(Array) then focus_model = a.select{|e| e.is_a?(Class)}.first data_model = a.select{|e| e.is_a?(Class)}.last else focus_model = data_model = a end line = QueryLine.new(models_path, access_filter) line.ids_rel.join_on_path_thru([focus_model, data_model]) line.ids_rel.apply_condition data_model.arel_primary_key.not_eq(nil) agg_only_lines << line end end end @lines += agg_only_lines end |
Instance Method Details
#run(cond = nil) ⇒ Object
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 96 97 98 |
# File 'lib/query.rb', line 70 def run(cond = nil) model_ids = {} parental_seqs = {} @lines.each do |line| tbl = line.build_id_table(cond) parent_models = [] line.layer_path.each do |model| tbl.each do |ids_row| i = ids_row["#{model.name}_id"] if i (model_ids[model] ||= Set.new).add(i) parental_seq_key = parent_models.zip( parent_models.map{|pm| ids_row["#{pm}_id"]} ) (parental_seqs[parental_seq_key] ||= Set.new).add([model.name, i]) end end parent_models << model.name end end model_datanodes = generate_datanodes(model_ids) root = create_root_node add_datanode_children([], root, model_datanodes, parental_seqs) @lines.each do |line| line.load_aggregate_data(root, cond) end return root end |