Skip to content

Commit 840dd8c

Browse files
authored
Merge 68b92ad into 6ab6f27
2 parents 6ab6f27 + 68b92ad commit 840dd8c

File tree

14 files changed

+298
-260
lines changed

14 files changed

+298
-260
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ Thank you to all who have contributed!
4747
- The new plan is fully resolved and typed.
4848
- Operators will be converted to function call.
4949
- Changes the return type of `filter_distinct` to a list if input collection is list
50+
- Changes the `PartiQLValue` collections to implement Iterable rather than Sequence, allowing for multiple consumption.
5051

5152
### Deprecated
5253

partiql-cli/src/main/kotlin/org/partiql/cli/utils/ServiceLoaderUtil.kt

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -268,28 +268,42 @@ class ServiceLoaderUtil {
268268
PartiQLValueType.INTERVAL -> TODO()
269269

270270
PartiQLValueType.BAG -> {
271-
(partiqlValue as? BagValue<*>)?.elements?.map { PartiQLtoExprValue(it) }?.let { newBag(it) }
272-
?: ExprValue.nullValue
271+
if (partiqlValue.isNull) {
272+
ExprValue.nullValue
273+
} else {
274+
newBag((partiqlValue as? BagValue<*>)!!.map { PartiQLtoExprValue(it) })
275+
}
273276
}
274277

275278
PartiQLValueType.LIST -> {
276-
(partiqlValue as? ListValue<*>)?.elements?.map { PartiQLtoExprValue(it) }?.let { newList(it) }
277-
?: ExprValue.nullValue
279+
if (partiqlValue.isNull) {
280+
ExprValue.nullValue
281+
} else {
282+
newList((partiqlValue as? ListValue<*>)!!.map { PartiQLtoExprValue(it) })
283+
}
278284
}
279285

280286
PartiQLValueType.SEXP -> {
281-
(partiqlValue as? SexpValue<*>)?.elements?.map { PartiQLtoExprValue(it) }?.let { newSexp(it) }
282-
?: ExprValue.nullValue
287+
if (partiqlValue.isNull) {
288+
ExprValue.nullValue
289+
} else {
290+
newSexp((partiqlValue as? SexpValue<*>)!!.map { PartiQLtoExprValue(it) })
291+
}
283292
}
284293

285294
PartiQLValueType.STRUCT -> {
286-
(partiqlValue as? StructValue<*>)?.fields?.map {
287-
PartiQLtoExprValue(it.second).namedValue(
288-
newString(
289-
it.first
295+
if (partiqlValue.isNull) {
296+
ExprValue.nullValue
297+
} else {
298+
val entries = (partiqlValue as? StructValue<*>)!!.entries
299+
entries.map {
300+
PartiQLtoExprValue(it.second).namedValue(
301+
newString(
302+
it.first
303+
)
290304
)
291-
)
292-
}?.let { newStruct(it, StructOrdering.ORDERED) } ?: ExprValue.nullValue
305+
}.let { newStruct(it, StructOrdering.ORDERED) }
306+
}
293307
}
294308

295309
PartiQLValueType.DECIMAL -> TODO()
@@ -447,7 +461,7 @@ class ServiceLoaderUtil {
447461
PartiQLValueType.INTERVAL -> TODO()
448462
PartiQLValueType.BAG -> when (exprValue.type) {
449463
ExprValueType.NULL -> bagValue(null)
450-
ExprValueType.BAG -> bagValue(exprValue.map { ExprToPartiQLValue(it, ExprToPartiQLValueType(it)) }.asSequence())
464+
ExprValueType.BAG -> bagValue(exprValue.map { ExprToPartiQLValue(it, ExprToPartiQLValueType(it)) })
451465
else -> throw ExprToPartiQLValueTypeMismatchException(
452466
PartiQLValueType.BAG, ExprToPartiQLValueType(exprValue)
453467
)
@@ -459,7 +473,7 @@ class ServiceLoaderUtil {
459473
ExprToPartiQLValue(
460474
it, ExprToPartiQLValueType(it)
461475
)
462-
}.asSequence()
476+
}
463477
)
464478
else -> throw ExprToPartiQLValueTypeMismatchException(
465479
PartiQLValueType.LIST, ExprToPartiQLValueType(exprValue)
@@ -472,7 +486,7 @@ class ServiceLoaderUtil {
472486
ExprToPartiQLValue(
473487
it, ExprToPartiQLValueType(it)
474488
)
475-
}.asSequence()
489+
}
476490
)
477491
else -> throw ExprToPartiQLValueTypeMismatchException(
478492
PartiQLValueType.SEXP, ExprToPartiQLValueType(exprValue)
@@ -485,7 +499,7 @@ class ServiceLoaderUtil {
485499
Pair(
486500
it.name?.stringValue() ?: "", ExprToPartiQLValue(it, ExprToPartiQLValueType(it))
487501
)
488-
}.asSequence()
502+
}
489503
)
490504
else -> throw ExprToPartiQLValueTypeMismatchException(
491505
PartiQLValueType.STRUCT, ExprToPartiQLValueType(exprValue)

partiql-types/src/main/kotlin/org/partiql/value/PartiQL.kt

Lines changed: 73 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@ import org.partiql.value.impl.Int64ValueImpl
3838
import org.partiql.value.impl.Int8ValueImpl
3939
import org.partiql.value.impl.IntValueImpl
4040
import org.partiql.value.impl.IntervalValueImpl
41+
import org.partiql.value.impl.IterableStructValueImpl
4142
import org.partiql.value.impl.ListValueImpl
4243
import org.partiql.value.impl.MapStructValueImpl
4344
import org.partiql.value.impl.MissingValueImpl
4445
import org.partiql.value.impl.MultiMapStructValueImpl
4546
import org.partiql.value.impl.NullValueImpl
46-
import org.partiql.value.impl.SequenceStructValueImpl
4747
import org.partiql.value.impl.SexpValueImpl
4848
import org.partiql.value.impl.StringValueImpl
4949
import org.partiql.value.impl.SymbolValueImpl
@@ -344,10 +344,25 @@ public fun intervalValue(
344344
@JvmOverloads
345345
@PartiQLValueExperimental
346346
public fun <T : PartiQLValue> bagValue(
347-
elements: Sequence<T>?,
347+
elements: Iterable<T>?,
348348
annotations: Annotations = emptyList(),
349349
): BagValue<T> = BagValueImpl(elements, annotations.toPersistentList())
350350

351+
/**
352+
* BAG type value.
353+
*
354+
* @param T
355+
* @param elements
356+
* @param annotations
357+
* @return
358+
*/
359+
@JvmOverloads
360+
@PartiQLValueExperimental
361+
public fun <T : PartiQLValue> bagValue(
362+
vararg elements: T,
363+
annotations: Annotations = emptyList(),
364+
): BagValue<T> = BagValueImpl(elements.asIterable(), annotations.toPersistentList())
365+
351366
/**
352367
* LIST type value.
353368
*
@@ -359,10 +374,25 @@ public fun <T : PartiQLValue> bagValue(
359374
@JvmOverloads
360375
@PartiQLValueExperimental
361376
public fun <T : PartiQLValue> listValue(
362-
elements: Sequence<T>?,
377+
elements: Iterable<T>?,
363378
annotations: Annotations = emptyList(),
364379
): ListValue<T> = ListValueImpl(elements, annotations.toPersistentList())
365380

381+
/**
382+
* LIST type value.
383+
*
384+
* @param T
385+
* @param elements
386+
* @param annotations
387+
* @return
388+
*/
389+
@JvmOverloads
390+
@PartiQLValueExperimental
391+
public fun <T : PartiQLValue> listValue(
392+
vararg elements: T,
393+
annotations: Annotations = emptyList(),
394+
): ListValue<T> = ListValueImpl(elements.asIterable(), annotations.toPersistentList())
395+
366396
/**
367397
* SEXP type value.
368398
*
@@ -374,12 +404,42 @@ public fun <T : PartiQLValue> listValue(
374404
@JvmOverloads
375405
@PartiQLValueExperimental
376406
public fun <T : PartiQLValue> sexpValue(
377-
elements: Sequence<T>?,
407+
elements: Iterable<T>?,
378408
annotations: Annotations = emptyList(),
379409
): SexpValue<T> = SexpValueImpl(elements, annotations.toPersistentList())
380410

381411
/**
382-
* STRUCT type value.
412+
* SEXP type value.
413+
*
414+
* @param T
415+
* @param elements
416+
* @param annotations
417+
* @return
418+
*/
419+
@JvmOverloads
420+
@PartiQLValueExperimental
421+
public fun <T : PartiQLValue> sexpValue(
422+
vararg elements: T,
423+
annotations: Annotations = emptyList(),
424+
): SexpValue<T> = SexpValueImpl(elements.asIterable(), annotations.toPersistentList())
425+
426+
/**
427+
* Create a PartiQL struct value backed by an iterable of key-value field pairs.
428+
*
429+
* @param T
430+
* @param fields
431+
* @param annotations
432+
* @return
433+
*/
434+
@JvmOverloads
435+
@PartiQLValueExperimental
436+
public fun <T : PartiQLValue> structValue(
437+
fields: Iterable<Pair<String, T>>?,
438+
annotations: Annotations = emptyList(),
439+
): StructValue<T> = IterableStructValueImpl(fields, annotations.toPersistentList())
440+
441+
/**
442+
* Create a PartiQL struct value backed by an iterable of key-value field pairs.
383443
*
384444
* @param T
385445
* @param fields
@@ -389,12 +449,13 @@ public fun <T : PartiQLValue> sexpValue(
389449
@JvmOverloads
390450
@PartiQLValueExperimental
391451
public fun <T : PartiQLValue> structValue(
392-
fields: Sequence<Pair<String, T>>?,
452+
vararg fields: Pair<String, T>,
393453
annotations: Annotations = emptyList(),
394-
): StructValue<T> = SequenceStructValueImpl(fields, annotations.toPersistentList())
454+
): StructValue<T> = IterableStructValueImpl(fields.toList(), annotations.toPersistentList())
395455

396456
/**
397-
* STRUCT type value.
457+
* Create a PartiQL struct value backed by a multimap of keys with a list of values. This supports having multiple
458+
* values per key, while improving lookup performance compared to using an iterable.
398459
*
399460
* @param T
400461
* @param fields
@@ -403,13 +464,14 @@ public fun <T : PartiQLValue> structValue(
403464
*/
404465
@JvmOverloads
405466
@PartiQLValueExperimental
406-
public fun <T : PartiQLValue> structValueWithDuplicates(
467+
public fun <T : PartiQLValue> structValueMultiMap(
407468
fields: Map<String, Iterable<T>>?,
408469
annotations: Annotations = emptyList(),
409470
): StructValue<T> = MultiMapStructValueImpl(fields, annotations.toPersistentList())
410471

411472
/**
412-
* STRUCT type value.
473+
* Create a PartiQL struct value backed by a map of keys with a list of values. This does not support having multiple
474+
* values per key, but uses a Java HashMap for quicker lookup than an iterable backed StructValue.
413475
*
414476
* @param T
415477
* @param fields
@@ -418,7 +480,7 @@ public fun <T : PartiQLValue> structValueWithDuplicates(
418480
*/
419481
@JvmOverloads
420482
@PartiQLValueExperimental
421-
public fun <T : PartiQLValue> structValueNoDuplicates(
483+
public fun <T : PartiQLValue> structValueMap(
422484
fields: Map<String, T>?,
423485
annotations: Annotations = emptyList(),
424486
): StructValue<T> = MapStructValueImpl(fields, annotations.toPersistentList())

partiql-types/src/main/kotlin/org/partiql/value/PartiQLValue.kt

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,11 @@ public sealed interface ScalarValue<T> : PartiQLValue {
6565
}
6666

6767
@PartiQLValueExperimental
68-
public sealed interface CollectionValue<T : PartiQLValue> : PartiQLValue, Sequence<T> {
69-
70-
public val elements: Sequence<T>?
68+
public sealed interface CollectionValue<T : PartiQLValue> : PartiQLValue, Iterable<T> {
7169

7270
override val isNull: Boolean
73-
get() = elements == null
7471

75-
override fun iterator(): Iterator<T> = elements!!.iterator()
72+
override fun iterator(): Iterator<T>
7673

7774
override fun copy(annotations: Annotations): CollectionValue<T>
7875

@@ -388,8 +385,8 @@ public abstract class BagValue<T : PartiQLValue> : CollectionValue<T> {
388385
if (this.isNull || other.isNull) return this.isNull == other.isNull
389386

390387
// both not null, compare values
391-
val lhs = this.elements!!.toList()
392-
val rhs = other.elements!!.toList()
388+
val lhs = this.toList()
389+
val rhs = other.toList()
393390
// this is incorrect as it assumes ordered-ness, but we don't have a sort or hash yet
394391
return lhs == rhs
395392
}
@@ -421,8 +418,8 @@ public abstract class ListValue<T : PartiQLValue> : CollectionValue<T> {
421418
if (this.isNull || other.isNull) return this.isNull == other.isNull
422419

423420
// both not null, compare values
424-
val lhs = this.elements!!.toList()
425-
val rhs = other.elements!!.toList()
421+
val lhs = this.toList()
422+
val rhs = other.toList()
426423
return lhs == rhs
427424
}
428425

@@ -452,8 +449,8 @@ public abstract class SexpValue<T : PartiQLValue> : CollectionValue<T> {
452449
if (this.isNull || other.isNull) return this.isNull == other.isNull
453450

454451
// both not null, compare values
455-
val lhs = this.elements!!.toList()
456-
val rhs = other.elements!!.toList()
452+
val lhs = this.toList()
453+
val rhs = other.toList()
457454
return lhs == rhs
458455
}
459456

@@ -464,16 +461,15 @@ public abstract class SexpValue<T : PartiQLValue> : CollectionValue<T> {
464461
}
465462

466463
@PartiQLValueExperimental
467-
public abstract class StructValue<T : PartiQLValue> : PartiQLValue, Sequence<Pair<String, T>> {
464+
public abstract class StructValue<T : PartiQLValue> : PartiQLValue {
468465

469466
override val type: PartiQLValueType = PartiQLValueType.STRUCT
470467

471-
public abstract val fields: Sequence<Pair<String, T>>?
468+
public abstract val fields: Iterable<String>
472469

473-
override val isNull: Boolean
474-
get() = fields == null
470+
public abstract val values: Iterable<T>
475471

476-
override fun iterator(): Iterator<Pair<String, T>> = fields!!.iterator()
472+
public abstract val entries: Iterable<Pair<String, T>>
477473

478474
public abstract operator fun get(key: String): T?
479475

@@ -486,9 +482,7 @@ public abstract class StructValue<T : PartiQLValue> : PartiQLValue, Sequence<Pai
486482
abstract override fun withoutAnnotations(): StructValue<T>
487483

488484
/**
489-
* See equality of IonElement StructElementImpl
490-
*
491-
* https://github.com/amazon-ion/ion-element-kotlin/blob/master/src/com/amazon/ionelement/impl/StructElementImpl.kt
485+
* Checks equality of struct entries, ignoring ordering.
492486
*
493487
* @param other
494488
* @return
@@ -502,15 +496,15 @@ public abstract class StructValue<T : PartiQLValue> : PartiQLValue, Sequence<Pai
502496
if (this.isNull || other.isNull) return this.isNull == other.isNull
503497

504498
// both not null, compare fields
505-
val lhs = this.fields!!.groupBy({ it.first }, { it.second })
506-
val rhs = other.fields!!.groupBy({ it.first }, { it.second })
499+
val lhs = this.entries.asIterable().groupBy({ it.first }, { it.second })
500+
val rhs = other.entries.asIterable().groupBy({ it.first }, { it.second })
507501

508502
// check size
509503
if (lhs.size != rhs.size) return false
510504
if (lhs.keys != rhs.keys) return false
511505

512506
// check values
513-
lhs.forEach { (key, values) ->
507+
lhs.entries.forEach { (key, values) ->
514508
val lGroup: Map<PartiQLValue, Int> = values.groupingBy { it }.eachCount()
515509
val rGroup: Map<PartiQLValue, Int> = rhs[key]!!.groupingBy { it }.eachCount()
516510
if (lGroup != rGroup) return false

partiql-types/src/main/kotlin/org/partiql/value/helpers/ToIon.kt

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -258,31 +258,31 @@ internal object ToIon : PartiQLValueBaseVisitor<IonElement, Unit>() {
258258
override fun visitInterval(v: IntervalValue, ctx: Unit): IonElement = TODO("Not Yet supported")
259259

260260
override fun visitBag(v: BagValue<*>, ctx: Unit): IonElement = v.annotate {
261-
when (val elements = v.elements) {
262-
null -> ionNull(ElementType.LIST)
263-
else -> ionListOf(elements.map { it.accept(ToIon, Unit) }.toList())
261+
when (v.isNull) {
262+
true -> ionNull(ElementType.LIST)
263+
else -> ionListOf(v.map { it.accept(ToIon, Unit) }.toList())
264264
}
265265
}.withAnnotations(BAG_ANNOTATION)
266266

267267
override fun visitList(v: ListValue<*>, ctx: Unit): IonElement = v.annotate {
268-
when (val elements = v.elements) {
269-
null -> ionNull(ElementType.LIST)
270-
else -> ionListOf(elements.map { it.accept(ToIon, Unit) }.toList())
268+
when (v.isNull) {
269+
true -> ionNull(ElementType.LIST)
270+
else -> ionListOf(v.map { it.accept(ToIon, Unit) }.toList())
271271
}
272272
}
273273

274274
override fun visitSexp(v: SexpValue<*>, ctx: Unit): IonElement = v.annotate {
275-
when (val elements = v.elements) {
276-
null -> ionNull(ElementType.SEXP)
277-
else -> ionSexpOf(elements.map { it.accept(ToIon, Unit) }.toList())
275+
when (v.isNull) {
276+
true -> ionNull(ElementType.SEXP)
277+
else -> ionSexpOf(v.map { it.accept(ToIon, Unit) }.toList())
278278
}
279279
}
280280

281281
override fun visitStruct(v: StructValue<*>, ctx: Unit): IonElement = v.annotate {
282-
when (val fields = v.fields) {
283-
null -> ionNull(ElementType.STRUCT)
282+
when (v.isNull) {
283+
true -> ionNull(ElementType.STRUCT)
284284
else -> {
285-
val ionFields = fields.map {
285+
val ionFields = entries.map {
286286
val fk = it.first
287287
val fv = it.second.accept(ToIon, ctx)
288288
field(fk, fv)

0 commit comments

Comments
 (0)