-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1438 from johnedquinn/v1-conformance-join
Simplifies joins and fixes bugs
- Loading branch information
Showing
18 changed files
with
641 additions
and
216 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
80 changes: 80 additions & 0 deletions
80
partiql-eval/src/main/kotlin/org/partiql/eval/internal/helpers/TypesUtility.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package org.partiql.eval.internal.helpers | ||
|
||
import org.partiql.types.AnyOfType | ||
import org.partiql.types.AnyType | ||
import org.partiql.types.BagType | ||
import org.partiql.types.BlobType | ||
import org.partiql.types.BoolType | ||
import org.partiql.types.ClobType | ||
import org.partiql.types.DateType | ||
import org.partiql.types.DecimalType | ||
import org.partiql.types.FloatType | ||
import org.partiql.types.GraphType | ||
import org.partiql.types.IntType | ||
import org.partiql.types.ListType | ||
import org.partiql.types.MissingType | ||
import org.partiql.types.NullType | ||
import org.partiql.types.SexpType | ||
import org.partiql.types.StaticType | ||
import org.partiql.types.StringType | ||
import org.partiql.types.StructType | ||
import org.partiql.types.SymbolType | ||
import org.partiql.types.TimeType | ||
import org.partiql.types.TimestampType | ||
import org.partiql.value.PartiQLValueExperimental | ||
import org.partiql.value.PartiQLValueType | ||
|
||
internal object TypesUtility { | ||
|
||
@OptIn(PartiQLValueExperimental::class) | ||
internal fun StaticType.toRuntimeType(): PartiQLValueType { | ||
if (this is AnyOfType) { | ||
// handle anyOf(null, T) cases | ||
val t = types.filter { it !is NullType && it !is MissingType } | ||
return if (t.size != 1) { | ||
PartiQLValueType.ANY | ||
} else { | ||
t.first().asRuntimeType() | ||
} | ||
} | ||
return this.asRuntimeType() | ||
} | ||
|
||
@OptIn(PartiQLValueExperimental::class) | ||
private fun StaticType.asRuntimeType(): PartiQLValueType = when (this) { | ||
is AnyOfType -> PartiQLValueType.ANY | ||
is AnyType -> PartiQLValueType.ANY | ||
is BlobType -> PartiQLValueType.BLOB | ||
is BoolType -> PartiQLValueType.BOOL | ||
is ClobType -> PartiQLValueType.CLOB | ||
is BagType -> PartiQLValueType.BAG | ||
is ListType -> PartiQLValueType.LIST | ||
is SexpType -> PartiQLValueType.SEXP | ||
is DateType -> PartiQLValueType.DATE | ||
// TODO: Run time decimal type does not model precision scale constraint yet | ||
// despite that we match to Decimal vs Decimal_ARBITRARY (PVT) here | ||
// but when mapping it back to Static Type, (i.e, mapping function return type to Value Type) | ||
// we can only map to Unconstrained decimal (Static Type) | ||
is DecimalType -> { | ||
when (this.precisionScaleConstraint) { | ||
is DecimalType.PrecisionScaleConstraint.Constrained -> PartiQLValueType.DECIMAL | ||
DecimalType.PrecisionScaleConstraint.Unconstrained -> PartiQLValueType.DECIMAL_ARBITRARY | ||
} | ||
} | ||
is FloatType -> PartiQLValueType.FLOAT64 | ||
is GraphType -> error("Graph type missing from runtime types") | ||
is IntType -> when (this.rangeConstraint) { | ||
IntType.IntRangeConstraint.SHORT -> PartiQLValueType.INT16 | ||
IntType.IntRangeConstraint.INT4 -> PartiQLValueType.INT32 | ||
IntType.IntRangeConstraint.LONG -> PartiQLValueType.INT64 | ||
IntType.IntRangeConstraint.UNCONSTRAINED -> PartiQLValueType.INT | ||
} | ||
MissingType -> PartiQLValueType.MISSING | ||
is NullType -> PartiQLValueType.NULL | ||
is StringType -> PartiQLValueType.STRING | ||
is StructType -> PartiQLValueType.STRUCT | ||
is SymbolType -> PartiQLValueType.SYMBOL | ||
is TimeType -> PartiQLValueType.TIME | ||
is TimestampType -> PartiQLValueType.TIMESTAMP | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 60 additions & 7 deletions
67
partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelJoinInner.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,70 @@ | ||
package org.partiql.eval.internal.operator.rel | ||
|
||
import org.partiql.eval.internal.Environment | ||
import org.partiql.eval.internal.Record | ||
import org.partiql.eval.internal.helpers.ValueUtility.isTrue | ||
import org.partiql.eval.internal.operator.Operator | ||
import org.partiql.value.PartiQLValueExperimental | ||
|
||
/** | ||
* Inner Join returns all joined records from the [lhs] and [rhs] when the [condition] evaluates to true. | ||
* | ||
* Note: This is currently the lateral version of the inner join. In the future, the two implementations | ||
* (lateral vs non-lateral) may be separated for performance improvements. | ||
*/ | ||
internal class RelJoinInner( | ||
override val lhs: Operator.Relation, | ||
override val rhs: Operator.Relation, | ||
override val condition: Operator.Expr, | ||
) : RelJoinNestedLoop() { | ||
override fun join(condition: Boolean, lhs: Record, rhs: Record): Record? { | ||
return when (condition) { | ||
true -> lhs + rhs | ||
private val lhs: Operator.Relation, | ||
private val rhs: Operator.Relation, | ||
private val condition: Operator.Expr, | ||
) : RelPeeking() { | ||
|
||
private lateinit var env: Environment | ||
private lateinit var iterator: Iterator<Record> | ||
|
||
override fun openPeeking(env: Environment) { | ||
this.env = env | ||
lhs.open(env) | ||
iterator = implementation() | ||
} | ||
|
||
override fun peek(): Record? { | ||
return when (iterator.hasNext()) { | ||
true -> iterator.next() | ||
false -> null | ||
} | ||
} | ||
|
||
override fun closePeeking() { | ||
lhs.close() | ||
rhs.close() | ||
iterator = emptyList<Record>().iterator() | ||
} | ||
|
||
/** | ||
* INNER JOIN (LATERAL) | ||
* | ||
* Algorithm: | ||
* ``` | ||
* for lhsRecord in lhs: | ||
* for rhsRecord in rhs(lhsRecord): | ||
* if (condition matches): | ||
* conditionMatched = true | ||
* yield(lhsRecord + rhsRecord) | ||
* ``` | ||
* | ||
* Development Note: The non-lateral version wouldn't need to push to the current environment. | ||
*/ | ||
@OptIn(PartiQLValueExperimental::class) | ||
private fun implementation() = iterator { | ||
for (lhsRecord in lhs) { | ||
rhs.open(env.push(lhsRecord)) | ||
for (rhsRecord in rhs) { | ||
val input = lhsRecord + rhsRecord | ||
val result = condition.eval(env.push(input)) | ||
if (result.isTrue()) { | ||
yield(lhsRecord + rhsRecord) | ||
} | ||
} | ||
} | ||
} | ||
} |
18 changes: 0 additions & 18 deletions
18
partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelJoinLeft.kt
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.