lib/conceptql/nodes/casting_node.rb in conceptql-0.0.3 vs lib/conceptql/nodes/casting_node.rb in conceptql-0.0.4

- old
+ new

@@ -22,13 +22,17 @@ # # Also, if a casting node is passed no streams, it will return all the # rows in its table as results. class CastingNode < Node def types - [my_type] + [type] end + def type + my_type + end + def castables (i_point_at + these_point_at_me) end def query(db) @@ -37,39 +41,55 @@ end private def base_query(db, stream_query) - if (stream.types & castables).length < stream.types.length - # We have a situation where one of the incoming streams + uncastable_types = stream.types - castables + to_me_types = stream.types & these_point_at_me + from_me_types = stream.types & i_point_at + + destination_table = make_table_name(my_type) + casting_query = db.from(destination_table) + wheres = [] + + unless uncastable_types.empty? + # We have a situation where one or more of the incoming streams # isn't castable so we'll just return all rows for - # all people - db.from(make_table_name(my_type)) - .where(person_id: db.from(stream_query).select_group(:person_id)) - else - # Every type in the stream is castable, so let's setup a query that + # all people in each uncastable stream + uncastable_person_ids = db.from(stream_query) + .where(criterion_type: uncastable_types.map(&:to_s)) + .select_group(:person_id) + wheres << Sequel.expr(person_id: uncastable_person_ids) + end + + destination_type_id = type_id(my_type) + + unless to_me_types.empty? + # For each castable type in the stream, setup a query that # casts each type to a set of IDs, union those IDs and fetch # them from the source table - my_ids = stream.types.map do |type| - cast_type(db, type, stream_query) - end.inject do |union_query, query| - union_query.union(query) - end + castable_type_queries = to_me_types.map do |source_type| + source_ids = db.from(stream_query) + .where(criterion_type: source_type.to_s) + .select_group(:criterion_id) + source_table = make_table_name(source_type) + source_type_id = type_id(source_type) - db.from(make_table_name(my_type)) - .where(type_id(my_type) => my_ids) + db.from(source_table) + .where(source_type_id => source_ids) + .select(destination_type_id) + end + wheres << Sequel.expr(destination_type_id => castable_type_queries) end - end - def cast_type(db, type, stream_query) - query = if i_point_at.include?(type) - db.from(make_table_name(my_type)) - .where(type_id(type) => db.from(stream_query.select_group(type_id(type)))) - else - db.from(make_table_name(type)) - .where(type_id(type) => db.from(stream_query.select_group(type_id(type)))) + unless from_me_types.empty? + from_me_types.each do |from_me_type| + fk_type_id = type_id(from_me_type) + wheres << Sequel.expr(fk_type_id => db.from(stream_query).where(criterion_type: from_me_type.to_s).select_group(:criterion_id)) + end end - query.select(type_id(my_type)) + + casting_query.where(wheres.inject(&:|)) end end end end