src/main/java/com/github/giedomak/telepath/physicaloperators/Union.kt
package com.github.giedomak.telepath.physicaloperators
import com.github.giedomak.telepath.datamodels.graph.PathStream
import com.github.giedomak.telepath.datamodels.plans.PhysicalPlan
import java.util.stream.Stream
/**
* Union physical operator.
*
* @property physicalPlan The physical plan where we have to perform the union on its children.
*/
class Union(override val physicalPlan: PhysicalPlan) : PhysicalOperator {
/**
* Evaluate the union.
*
* Default behaviour is to filter out duplicates, just like in other DBMS.
*
* @return A path stream with the resulting elements.
*/
override fun evaluate(): PathStream {
return PathStream(
physicalPlan.query.telepath,
Stream.concat(
firstChild.evaluate().paths,
lastChild.evaluate().paths
).distinct()
)
}
/**
* Cost of the union operation.
*/
override fun cost(): Long {
// Cost to produce results.
val myCost = firstChild.cardinality + lastChild.cardinality
// Our input sets might be intermediate results, so take their cost into account.
val cost1 = firstChild.cost()
val cost2 = lastChild.cost()
// Overflow check
if (myCost == Long.MAX_VALUE || cost1 == Long.MAX_VALUE || cost2 == Long.MAX_VALUE) return Long.MAX_VALUE
return myCost + cost1 + cost2
}
}