Skip to content

Commit 9e9a040

Browse files
committed
Move around top-level fns; make EXCLUDE input private
1 parent 5bc681e commit 9e9a040

File tree

3 files changed

+156
-154
lines changed

3 files changed

+156
-154
lines changed

partiql-eval/src/main/kotlin/org/partiql/eval/internal/Compiler.kt

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package org.partiql.eval.internal
22

3+
import org.partiql.eval.internal.exclude.CompiledExcludeItem
4+
import org.partiql.eval.internal.exclude.ExcludeFieldCase
5+
import org.partiql.eval.internal.exclude.ExcludeStep
36
import org.partiql.eval.internal.operator.Operator
47
import org.partiql.eval.internal.operator.rel.RelDistinct
58
import org.partiql.eval.internal.operator.rel.RelExclude
@@ -11,7 +14,6 @@ import org.partiql.eval.internal.operator.rel.RelJoinRight
1114
import org.partiql.eval.internal.operator.rel.RelProject
1215
import org.partiql.eval.internal.operator.rel.RelScan
1316
import org.partiql.eval.internal.operator.rel.RelScanIndexed
14-
import org.partiql.eval.internal.operator.rel.compileExcludeItems
1517
import org.partiql.eval.internal.operator.rex.ExprCase
1618
import org.partiql.eval.internal.operator.rex.ExprCollection
1719
import org.partiql.eval.internal.operator.rex.ExprGlobal
@@ -24,6 +26,7 @@ import org.partiql.eval.internal.operator.rex.ExprSelect
2426
import org.partiql.eval.internal.operator.rex.ExprStruct
2527
import org.partiql.eval.internal.operator.rex.ExprTupleUnion
2628
import org.partiql.eval.internal.operator.rex.ExprVar
29+
import org.partiql.plan.Identifier
2730
import org.partiql.plan.PartiQLPlan
2831
import org.partiql.plan.PlanNode
2932
import org.partiql.plan.Rel
@@ -188,6 +191,38 @@ internal class Compiler(
188191
return RelFilter(input, condition)
189192
}
190193

194+
/**
195+
* Creates a list of [CompiledExcludeItem] with each index of the resulting list corresponding to a different
196+
* exclude path root.
197+
*/
198+
internal fun compileExcludeItems(excludeExprs: List<Rel.Op.Exclude.Item>): List<CompiledExcludeItem> {
199+
val compiledExcludeItems = excludeExprs
200+
.groupBy { it.root }
201+
.map { (root, exclusions) ->
202+
exclusions.fold(CompiledExcludeItem.empty(root.ref)) { acc, exclusion ->
203+
acc.addNode(exclusion.steps.map { it.toCompiledExcludeStep() })
204+
acc
205+
}
206+
}
207+
return compiledExcludeItems
208+
}
209+
210+
private fun Rel.Op.Exclude.Step.toCompiledExcludeStep(): ExcludeStep {
211+
return when (this) {
212+
is Rel.Op.Exclude.Step.StructField -> ExcludeStep.StructField(this.symbol.symbol, this.symbol.caseSensitivity.toCompiledExcludeStepCase())
213+
is Rel.Op.Exclude.Step.StructWildcard -> ExcludeStep.StructWildcard
214+
is Rel.Op.Exclude.Step.CollIndex -> ExcludeStep.CollIndex(this.index)
215+
is Rel.Op.Exclude.Step.CollWildcard -> ExcludeStep.CollWildcard
216+
}
217+
}
218+
219+
private fun Identifier.CaseSensitivity.toCompiledExcludeStepCase(): ExcludeFieldCase {
220+
return when (this) {
221+
Identifier.CaseSensitivity.SENSITIVE -> ExcludeFieldCase.SENSITIVE
222+
Identifier.CaseSensitivity.INSENSITIVE -> ExcludeFieldCase.INSENSITIVE
223+
}
224+
}
225+
191226
override fun visitRelOpExclude(node: Rel.Op.Exclude, ctx: Unit): Operator {
192227
val input = visitRel(node.input, ctx)
193228
val compiledExcludeExprs = compileExcludeItems(node.items)

partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelExclude.kt

Lines changed: 115 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import org.partiql.eval.internal.exclude.ExcludeFieldCase
66
import org.partiql.eval.internal.exclude.ExcludeNode
77
import org.partiql.eval.internal.exclude.ExcludeStep
88
import org.partiql.eval.internal.operator.Operator
9-
import org.partiql.plan.Identifier
10-
import org.partiql.plan.Rel
119
import org.partiql.value.BagValue
1210
import org.partiql.value.CollectionValue
1311
import org.partiql.value.ListValue
@@ -22,8 +20,8 @@ import org.partiql.value.sexpValue
2220
import org.partiql.value.structValue
2321

2422
internal class RelExclude(
25-
val input: Operator.Relation,
26-
private val compiledExcludeItems: List<CompiledExcludeItem>
23+
private val input: Operator.Relation,
24+
private val exclusions: List<CompiledExcludeItem>
2725
) : Operator.Relation {
2826

2927
override fun open() {
@@ -33,7 +31,7 @@ internal class RelExclude(
3331
override fun next(): Record? {
3432
while (true) {
3533
val row = input.next() ?: return null
36-
val newRecord = compiledExcludeItems.fold(row) { curRecord, expr ->
34+
val newRecord = exclusions.fold(row) { curRecord, expr ->
3735
excludeOnRecord(curRecord, expr)
3836
}
3937
return newRecord
@@ -43,170 +41,138 @@ internal class RelExclude(
4341
override fun close() {
4442
input.close()
4543
}
46-
}
4744

48-
@OptIn(PartiQLValueExperimental::class)
49-
private fun excludeOnRecord(
50-
record: Record,
51-
exclusions: CompiledExcludeItem
52-
): Record {
53-
val values = record.values
54-
val value = values.getOrNull(exclusions.root)
55-
val newValues = if (value != null) {
56-
values[exclusions.root] = excludeOnPartiQLValue(value, exclusions)
57-
values
58-
} else {
59-
values
60-
}
61-
return Record(newValues)
62-
}
63-
64-
@OptIn(PartiQLValueExperimental::class)
65-
private fun excludeOnStructValue(
66-
structValue: StructValue<*>,
67-
exclusions: ExcludeNode
68-
): PartiQLValue {
69-
val leavesSteps = exclusions.leaves.map { leaf -> leaf.step }
70-
val branches = exclusions.branches
71-
if (leavesSteps.any { it is ExcludeStep.StructWildcard }) {
72-
// tuple wildcard at current level. return empty struct
73-
return structValue<PartiQLValue>()
74-
}
75-
val attrsToRemove = leavesSteps.filterIsInstance<ExcludeStep.StructField>()
76-
.map { it.attr }
77-
.toSet()
78-
val entriesWithRemoved = structValue.entries.filter { structField ->
79-
!attrsToRemove.contains(structField.first)
80-
}
81-
val finalStruct = entriesWithRemoved.map { structField ->
82-
val name = structField.first
83-
var expr = structField.second
84-
// apply case-sensitive tuple attr exclusions
85-
val structFieldCaseSensitiveKey = ExcludeStep.StructField(name, ExcludeFieldCase.SENSITIVE)
86-
branches.find {
87-
it.step == structFieldCaseSensitiveKey
88-
}?.let {
89-
expr = excludeOnPartiQLValue(expr, it)
90-
}
91-
// apply case-insensitive tuple attr exclusions
92-
val structFieldCaseInsensitiveKey = ExcludeStep.StructField(name, ExcludeFieldCase.INSENSITIVE)
93-
branches.find {
94-
it.step == structFieldCaseInsensitiveKey
95-
}?.let {
96-
expr = excludeOnPartiQLValue(expr, it)
97-
}
98-
// apply tuple wildcard exclusions
99-
val tupleWildcardKey = ExcludeStep.StructWildcard
100-
branches.find {
101-
it.step == tupleWildcardKey
102-
}?.let {
103-
expr = excludeOnPartiQLValue(expr, it)
45+
@OptIn(PartiQLValueExperimental::class)
46+
private fun excludeOnRecord(
47+
record: Record,
48+
exclusions: CompiledExcludeItem
49+
): Record {
50+
val values = record.values
51+
val value = values.getOrNull(exclusions.root)
52+
val newValues = if (value != null) {
53+
values[exclusions.root] = excludeOnPartiQLValue(value, exclusions)
54+
values
55+
} else {
56+
values
10457
}
105-
Pair(name, expr)
58+
return Record(newValues)
10659
}
107-
return structValue(finalStruct)
108-
}
10960

110-
/**
111-
* Returns a [PartiQLValue] created from an iterable of [coll]. Requires [type] to be a collection type
112-
* (i.e. [PartiQLValueType.LIST], [PartiQLValueType.BAG], or [PartiQLValueType.SEXP]).
113-
*/
114-
@OptIn(PartiQLValueExperimental::class)
115-
private fun newCollValue(type: PartiQLValueType, coll: Iterable<PartiQLValue>): PartiQLValue {
116-
return when (type) {
117-
PartiQLValueType.LIST -> listValue(coll)
118-
PartiQLValueType.BAG -> bagValue(coll)
119-
PartiQLValueType.SEXP -> sexpValue(coll)
120-
else -> error("Collection type required")
121-
}
122-
}
123-
124-
@OptIn(PartiQLValueExperimental::class)
125-
private fun excludeOnCollValue(
126-
coll: CollectionValue<*>,
127-
type: PartiQLValueType,
128-
exclusions: ExcludeNode
129-
): PartiQLValue {
130-
val leavesSteps = exclusions.leaves.map { leaf -> leaf.step }
131-
val branches = exclusions.branches
132-
if (leavesSteps.any { it is ExcludeStep.CollWildcard }) {
133-
// collection wildcard at current level. return empty collection
134-
return newCollValue(type, emptyList())
135-
} else {
136-
val indexesToRemove = leavesSteps.filterIsInstance<ExcludeStep.CollIndex>()
137-
.map { it.index }
61+
@OptIn(PartiQLValueExperimental::class)
62+
private fun excludeOnStructValue(
63+
structValue: StructValue<*>,
64+
exclusions: ExcludeNode
65+
): PartiQLValue {
66+
val leavesSteps = exclusions.leaves.map { leaf -> leaf.step }
67+
val branches = exclusions.branches
68+
if (leavesSteps.any { it is ExcludeStep.StructWildcard }) {
69+
// tuple wildcard at current level. return empty struct
70+
return structValue<PartiQLValue>()
71+
}
72+
val attrsToRemove = leavesSteps.filterIsInstance<ExcludeStep.StructField>()
73+
.map { it.attr }
13874
.toSet()
139-
val collWithRemoved = when (coll) {
140-
is BagValue -> coll
141-
is ListValue, is SexpValue -> coll.filterIndexed { index, _ ->
142-
!indexesToRemove.contains(index)
143-
}
75+
val entriesWithRemoved = structValue.entries.filter { structField ->
76+
!attrsToRemove.contains(structField.first)
14477
}
145-
val finalColl = collWithRemoved.mapIndexed { index, element ->
146-
var expr = element
147-
if (coll is ListValue || coll is SexpValue) {
148-
// apply collection index exclusions for lists and sexps
149-
val elementKey = ExcludeStep.CollIndex(index)
150-
branches.find {
151-
it.step == elementKey
152-
}?.let {
153-
expr = excludeOnPartiQLValue(element, it)
154-
}
78+
val finalStruct = entriesWithRemoved.map { structField ->
79+
val name = structField.first
80+
var expr = structField.second
81+
// apply case-sensitive tuple attr exclusions
82+
val structFieldCaseSensitiveKey = ExcludeStep.StructField(name, ExcludeFieldCase.SENSITIVE)
83+
branches.find {
84+
it.step == structFieldCaseSensitiveKey
85+
}?.let {
86+
expr = excludeOnPartiQLValue(expr, it)
87+
}
88+
// apply case-insensitive tuple attr exclusions
89+
val structFieldCaseInsensitiveKey = ExcludeStep.StructField(name, ExcludeFieldCase.INSENSITIVE)
90+
branches.find {
91+
it.step == structFieldCaseInsensitiveKey
92+
}?.let {
93+
expr = excludeOnPartiQLValue(expr, it)
15594
}
156-
// apply collection wildcard exclusions for lists, bags, and sexps
157-
val collectionWildcardKey = ExcludeStep.CollWildcard
95+
// apply tuple wildcard exclusions
96+
val tupleWildcardKey = ExcludeStep.StructWildcard
15897
branches.find {
159-
it.step == collectionWildcardKey
98+
it.step == tupleWildcardKey
16099
}?.let {
161100
expr = excludeOnPartiQLValue(expr, it)
162101
}
163-
expr
102+
Pair(name, expr)
164103
}
165-
return newCollValue(type, finalColl)
104+
return structValue(finalStruct)
166105
}
167-
}
168106

169-
@OptIn(PartiQLValueExperimental::class)
170-
private fun excludeOnPartiQLValue(initialPartiQLValue: PartiQLValue, exclusions: ExcludeNode): PartiQLValue {
171-
return when (initialPartiQLValue) {
172-
is StructValue<*> -> excludeOnStructValue(initialPartiQLValue, exclusions)
173-
is BagValue<*> -> excludeOnCollValue(initialPartiQLValue, PartiQLValueType.BAG, exclusions)
174-
is ListValue<*> -> excludeOnCollValue(initialPartiQLValue, PartiQLValueType.LIST, exclusions)
175-
is SexpValue<*> -> excludeOnCollValue(initialPartiQLValue, PartiQLValueType.SEXP, exclusions)
176-
else -> {
177-
initialPartiQLValue
107+
/**
108+
* Returns a [PartiQLValue] created from an iterable of [coll]. Requires [type] to be a collection type
109+
* (i.e. [PartiQLValueType.LIST], [PartiQLValueType.BAG], or [PartiQLValueType.SEXP]).
110+
*/
111+
@OptIn(PartiQLValueExperimental::class)
112+
private fun newCollValue(type: PartiQLValueType, coll: Iterable<PartiQLValue>): PartiQLValue {
113+
return when (type) {
114+
PartiQLValueType.LIST -> listValue(coll)
115+
PartiQLValueType.BAG -> bagValue(coll)
116+
PartiQLValueType.SEXP -> sexpValue(coll)
117+
else -> error("Collection type required")
178118
}
179119
}
180-
}
181120

182-
/**
183-
* Creates a list of [CompiledExcludeItem] with each index of the resulting list corresponding to a different
184-
* exclude path root.
185-
*/
186-
internal fun compileExcludeItems(excludeExprs: List<Rel.Op.Exclude.Item>): List<CompiledExcludeItem> {
187-
val compiledExcludeItems = excludeExprs
188-
.groupBy { it.root }
189-
.map { (root, exclusions) ->
190-
exclusions.fold(CompiledExcludeItem.empty(root.ref)) { acc, exclusion ->
191-
acc.addNode(exclusion.steps.map { it.toCompiledExcludeStep() })
192-
acc
121+
@OptIn(PartiQLValueExperimental::class)
122+
private fun excludeOnCollValue(
123+
coll: CollectionValue<*>,
124+
type: PartiQLValueType,
125+
exclusions: ExcludeNode
126+
): PartiQLValue {
127+
val leavesSteps = exclusions.leaves.map { leaf -> leaf.step }
128+
val branches = exclusions.branches
129+
if (leavesSteps.any { it is ExcludeStep.CollWildcard }) {
130+
// collection wildcard at current level. return empty collection
131+
return newCollValue(type, emptyList())
132+
} else {
133+
val indexesToRemove = leavesSteps.filterIsInstance<ExcludeStep.CollIndex>()
134+
.map { it.index }
135+
.toSet()
136+
val collWithRemoved = when (coll) {
137+
is BagValue -> coll
138+
is ListValue, is SexpValue -> coll.filterIndexed { index, _ ->
139+
!indexesToRemove.contains(index)
140+
}
141+
}
142+
val finalColl = collWithRemoved.mapIndexed { index, element ->
143+
var expr = element
144+
if (coll is ListValue || coll is SexpValue) {
145+
// apply collection index exclusions for lists and sexps
146+
val elementKey = ExcludeStep.CollIndex(index)
147+
branches.find {
148+
it.step == elementKey
149+
}?.let {
150+
expr = excludeOnPartiQLValue(element, it)
151+
}
152+
}
153+
// apply collection wildcard exclusions for lists, bags, and sexps
154+
val collectionWildcardKey = ExcludeStep.CollWildcard
155+
branches.find {
156+
it.step == collectionWildcardKey
157+
}?.let {
158+
expr = excludeOnPartiQLValue(expr, it)
159+
}
160+
expr
193161
}
162+
return newCollValue(type, finalColl)
194163
}
195-
return compiledExcludeItems
196-
}
197-
198-
private fun Rel.Op.Exclude.Step.toCompiledExcludeStep(): ExcludeStep {
199-
return when (this) {
200-
is Rel.Op.Exclude.Step.StructField -> ExcludeStep.StructField(this.symbol.symbol, this.symbol.caseSensitivity.toCompiledExcludeStepCase())
201-
is Rel.Op.Exclude.Step.StructWildcard -> ExcludeStep.StructWildcard
202-
is Rel.Op.Exclude.Step.CollIndex -> ExcludeStep.CollIndex(this.index)
203-
is Rel.Op.Exclude.Step.CollWildcard -> ExcludeStep.CollWildcard
204164
}
205-
}
206165

207-
private fun Identifier.CaseSensitivity.toCompiledExcludeStepCase(): ExcludeFieldCase {
208-
return when (this) {
209-
Identifier.CaseSensitivity.SENSITIVE -> ExcludeFieldCase.SENSITIVE
210-
Identifier.CaseSensitivity.INSENSITIVE -> ExcludeFieldCase.INSENSITIVE
166+
@OptIn(PartiQLValueExperimental::class)
167+
private fun excludeOnPartiQLValue(initialPartiQLValue: PartiQLValue, exclusions: ExcludeNode): PartiQLValue {
168+
return when (initialPartiQLValue) {
169+
is StructValue<*> -> excludeOnStructValue(initialPartiQLValue, exclusions)
170+
is BagValue<*> -> excludeOnCollValue(initialPartiQLValue, PartiQLValueType.BAG, exclusions)
171+
is ListValue<*> -> excludeOnCollValue(initialPartiQLValue, PartiQLValueType.LIST, exclusions)
172+
is SexpValue<*> -> excludeOnCollValue(initialPartiQLValue, PartiQLValueType.SEXP, exclusions)
173+
else -> {
174+
initialPartiQLValue
175+
}
176+
}
211177
}
212178
}

partiql-eval/src/test/kotlin/org/partiql/eval/internal/exclude/CompiledExcludeItemTest.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package org.partiql.eval.internal.exclude
33
import org.junit.Assert.assertEquals
44
import org.junit.jupiter.params.ParameterizedTest
55
import org.junit.jupiter.params.provider.ArgumentsSource
6-
import org.partiql.eval.internal.operator.rel.compileExcludeItems
6+
import org.partiql.eval.internal.Compiler
77
import org.partiql.lang.util.ArgumentsProviderBase
88
import org.partiql.parser.PartiQLParser
99
import org.partiql.plan.Rel
@@ -24,9 +24,10 @@ class CompiledExcludeItemTest {
2424
private fun testExcludeExprSubsumption(tc: SubsumptionTC) {
2525
val statement = parser.parse("SELECT * EXCLUDE ${tc.excludeExprStr} FROM <<>> AS s, <<>> AS t;").root
2626
val session = PartiQLPlanner.Session("q", "u")
27-
val plan = planner.plan(statement, session)
28-
val excludeClause = getExcludeClause(plan.plan.statement)
29-
val actualExcludeExprs = compileExcludeItems(excludeClause.items)
27+
val plan = planner.plan(statement, session).plan
28+
val compiler = Compiler(plan, emptyMap())
29+
val excludeClause = getExcludeClause(plan.statement)
30+
val actualExcludeExprs = compiler.compileExcludeItems(excludeClause.items)
3031
assertEquals(tc.expectedExcludeExprs, actualExcludeExprs)
3132
}
3233

0 commit comments

Comments
 (0)