From c70c53d36da072ecb83afc6cdf04624a682f2a34 Mon Sep 17 00:00:00 2001 From: "R. C. Howell" Date: Mon, 19 Jun 2023 14:01:46 -0700 Subject: [PATCH] Adds nullable value interfaces and implementations --- .../org/partiql/types/PartiQLValueType.kt | 29 +- .../kotlin/org/partiql/value/Constructors.kt | 429 ++++++++++++++- .../kotlin/org/partiql/value/PartiQLValue.kt | 45 +- .../org/partiql/value/PartiQLValueNullable.kt | 387 ++++++++++++++ .../org/partiql/value/PartiQLValueVisitor.kt | 171 +++++- .../partiql/value/impl/PartiQLValueImpl.kt | 40 +- .../value/impl/PartiQLValueNullableImpl.kt | 496 ++++++++++++++++++ .../value/impl/PartiQLValueTextWriter.kt | 113 +++- .../value/impl/PartiQLValueTextWriterTest.kt | 172 +++++- 9 files changed, 1763 insertions(+), 119 deletions(-) create mode 100644 partiql-types/src/main/kotlin/org/partiql/value/PartiQLValueNullable.kt create mode 100644 partiql-types/src/main/kotlin/org/partiql/value/impl/PartiQLValueNullableImpl.kt diff --git a/partiql-types/src/main/kotlin/org/partiql/types/PartiQLValueType.kt b/partiql-types/src/main/kotlin/org/partiql/types/PartiQLValueType.kt index 0703098207..d5da2aea0a 100644 --- a/partiql-types/src/main/kotlin/org/partiql/types/PartiQLValueType.kt +++ b/partiql-types/src/main/kotlin/org/partiql/types/PartiQLValueType.kt @@ -18,8 +18,6 @@ package org.partiql.types * PartiQL Type Names */ public enum class PartiQLValueType { - NULL, - MISSING, BOOL, INT8, INT16, @@ -32,7 +30,6 @@ public enum class PartiQLValueType { CHAR, STRING, SYMBOL, - BIT, BINARY, BYTE, BLOB, @@ -45,4 +42,30 @@ public enum class PartiQLValueType { LIST, SEXP, STRUCT, + NULL, // null.null + MISSING, // missing + NULLABLE_BOOL, // null.bool + NULLABLE_INT8, // null.int8 + NULLABLE_INT16, // null.int16 + NULLABLE_INT32, // null.int32 + NULLABLE_INT64, // null.int64 + NULLABLE_INT, // null.int + NULLABLE_DECIMAL, // null.decimal + NULLABLE_FLOAT32, // null.float32 + NULLABLE_FLOAT64, // null.float64 + NULLABLE_CHAR, // null.char + NULLABLE_STRING, // null.string + NULLABLE_SYMBOL, // null.symbol + NULLABLE_BINARY, // null.binary + NULLABLE_BYTE, // null.byte + NULLABLE_BLOB, // null.blob + NULLABLE_CLOB, // null.clob + NULLABLE_DATE, // null.date + NULLABLE_TIME, // null.time + NULLABLE_TIMESTAMP, // null.timestamp + NULLABLE_INTERVAL, // null.interval + NULLABLE_BAG, // null.bag + NULLABLE_LIST, // null.list + NULLABLE_SEXP, // null.sexp + NULLABLE_STRUCT, // null.struct } diff --git a/partiql-types/src/main/kotlin/org/partiql/value/Constructors.kt b/partiql-types/src/main/kotlin/org/partiql/value/Constructors.kt index 47f50fc09d..a30ed36640 100644 --- a/partiql-types/src/main/kotlin/org/partiql/value/Constructors.kt +++ b/partiql-types/src/main/kotlin/org/partiql/value/Constructors.kt @@ -37,6 +37,30 @@ import org.partiql.value.impl.IntervalValueImpl import org.partiql.value.impl.ListValueImpl import org.partiql.value.impl.MissingValueImpl import org.partiql.value.impl.NullValueImpl +import org.partiql.value.impl.NullableBagValueImpl +import org.partiql.value.impl.NullableBinaryValueImpl +import org.partiql.value.impl.NullableBlobValueImpl +import org.partiql.value.impl.NullableBoolValueImpl +import org.partiql.value.impl.NullableByteValueImpl +import org.partiql.value.impl.NullableCharValueImpl +import org.partiql.value.impl.NullableClobValueImpl +import org.partiql.value.impl.NullableDateValueImpl +import org.partiql.value.impl.NullableDecimalValueImpl +import org.partiql.value.impl.NullableFloat32ValueImpl +import org.partiql.value.impl.NullableFloat64ValueImpl +import org.partiql.value.impl.NullableInt16ValueImpl +import org.partiql.value.impl.NullableInt32ValueImpl +import org.partiql.value.impl.NullableInt64ValueImpl +import org.partiql.value.impl.NullableInt8ValueImpl +import org.partiql.value.impl.NullableIntValueImpl +import org.partiql.value.impl.NullableIntervalValueImpl +import org.partiql.value.impl.NullableListValueImpl +import org.partiql.value.impl.NullableSexpValueImpl +import org.partiql.value.impl.NullableStringValueImpl +import org.partiql.value.impl.NullableStructValueImpl +import org.partiql.value.impl.NullableSymbolValueImpl +import org.partiql.value.impl.NullableTimeValueImpl +import org.partiql.value.impl.NullableTimestampValueImpl import org.partiql.value.impl.SexpValueImpl import org.partiql.value.impl.StringValueImpl import org.partiql.value.impl.StructValueImpl @@ -48,30 +72,8 @@ import java.math.BigInteger import java.time.LocalDate import java.time.LocalDateTime import java.time.LocalTime +import java.time.ZoneOffset import java.util.BitSet -import java.util.TimeZone - -/** - * TODO - * - * @param annotations - * @return - */ -@JvmOverloads -public fun nullValue( - annotations: Annotations = emptyList(), -): NullValue = NullValueImpl(annotations.toPersistentList()) - -/** - * TODO - * - * @param annotations - * @return - */ -@JvmOverloads -public fun missingValue( - annotations: Annotations = emptyList(), -): MissingValue = MissingValueImpl(annotations.toPersistentList()) /** * TODO @@ -305,9 +307,10 @@ public fun dateValue( public fun timeValue( value: LocalTime, precision: Int = 0, - timeZone: TimeZone? = null, + offset: ZoneOffset? = null, + withZone: Boolean = false, annotations: Annotations = emptyList(), -): TimeValue = TimeValueImpl(value, precision, timeZone, annotations.toPersistentList()) +): TimeValue = TimeValueImpl(value, precision, offset, withZone, annotations.toPersistentList()) /** * TODO @@ -320,9 +323,10 @@ public fun timeValue( public fun timestampValue( value: LocalDateTime, precision: Int = 0, - timeZone: TimeZone? = null, + offset: ZoneOffset? = null, + withZone: Boolean = false, annotations: Annotations = emptyList(), -): TimestampValue = TimestampValueImpl(value, precision, timeZone, annotations.toPersistentList()) +): TimestampValue = TimestampValueImpl(value, precision, offset, withZone, annotations.toPersistentList()) /** * TODO @@ -392,3 +396,374 @@ public fun structValue( fields: List>, annotations: Annotations = emptyList(), ): StructValue = StructValueImpl(fields.toPersistentList(), annotations.toPersistentList()) + +// +// NULLABLE VALUE CONSTRUCTORS +// + +/** + * TODO + * + * @param annotations + * @return + */ +@JvmOverloads +public fun nullValue( + annotations: Annotations = emptyList(), +): NullValue = NullValueImpl(annotations.toPersistentList()) + +/** + * TODO + * + * @param annotations + * @return + */ +@JvmOverloads +public fun missingValue( + annotations: Annotations = emptyList(), +): MissingValue = MissingValueImpl(annotations.toPersistentList()) + +/** + * TODO + * + * @param value + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableBoolValue( + value: Boolean? = null, + annotations: Annotations = emptyList(), +): NullableBoolValue = NullableBoolValueImpl(value, annotations.toPersistentList()) + +/** + * TODO + * + * @param value + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableInt8Value( + value: Byte? = null, + annotations: Annotations = emptyList(), +): NullableInt8Value = NullableInt8ValueImpl(value, annotations.toPersistentList()) + +/** + * TODO + * + * @param value + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableInt16Value( + value: Short? = null, + annotations: Annotations = emptyList(), +): NullableInt16Value = NullableInt16ValueImpl(value, annotations.toPersistentList()) + +/** + * TODO + * + * @param value + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableInt32Value( + value: Int? = null, + annotations: Annotations = emptyList(), +): NullableInt32Value = NullableInt32ValueImpl(value, annotations.toPersistentList()) + +/** + * TODO + * + * @param value + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableInt64Value( + value: Long? = null, + annotations: Annotations = emptyList(), +): NullableInt64Value = NullableInt64ValueImpl(value, annotations.toPersistentList()) + +/** + * TODO + * + * @param value + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableIntValue( + value: BigInteger? = null, + annotations: Annotations = emptyList(), +): NullableIntValue = NullableIntValueImpl(value, annotations.toPersistentList()) + +/** + * TODO + * + * @param value + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableDecimalValue( + value: BigDecimal? = null, + annotations: Annotations = emptyList(), +): NullableDecimalValue = NullableDecimalValueImpl(value, annotations.toPersistentList()) + +/** + * TODO + * + * @param value + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableFloat32Value( + value: Float? = null, + annotations: Annotations = emptyList(), +): NullableFloat32Value = NullableFloat32ValueImpl(value, annotations.toPersistentList()) + +/** + * TODO + * + * @param value + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableFloat64Value( + value: Double? = null, + annotations: Annotations = emptyList(), +): NullableFloat64Value = NullableFloat64ValueImpl(value, annotations.toPersistentList()) + +/** + * TODO + * + * @param value + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableCharValue( + value: Char? = null, + annotations: Annotations = emptyList(), +): NullableCharValue = NullableCharValueImpl(value, annotations.toPersistentList()) + +/** + * TODO + * + * @param value + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableStringValue( + value: String? = null, + annotations: Annotations = emptyList(), +): NullableStringValue = NullableStringValueImpl(value, annotations.toPersistentList()) + +/** + * TODO + * + * @param value + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableSymbolValue( + value: String? = null, + annotations: Annotations = emptyList(), +): NullableSymbolValue = NullableSymbolValueImpl(value, annotations.toPersistentList()) + +/** + * TODO + * + * @param value + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableClobValue( + value: ByteArray? = null, + annotations: Annotations = emptyList(), +): NullableClobValue = NullableClobValueImpl(value, annotations.toPersistentList()) + +/** + * TODO + * + * @param value + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableBinaryValue( + value: BitSet? = null, + annotations: Annotations = emptyList(), +): NullableBinaryValue = NullableBinaryValueImpl(value, annotations.toPersistentList()) + +/** + * TODO + * + * @param value + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableByteValue( + value: Byte? = null, + annotations: Annotations = emptyList(), +): NullableByteValue = NullableByteValueImpl(value, annotations.toPersistentList()) + +/** + * TODO + * + * @param value + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableBlobValue( + value: ByteArray? = null, + annotations: Annotations = emptyList(), +): NullableBlobValue = NullableBlobValueImpl(value, annotations.toPersistentList()) + +/** + * TODO + * + * @param value + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableDateValue( + value: LocalDate? = null, + annotations: Annotations = emptyList(), +): NullableDateValue = NullableDateValueImpl(value, annotations.toPersistentList()) + +/** + * TODO + * + * @param value + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableTimeValue( + annotations: Annotations = emptyList(), +): NullableTimeValue = NullableTimeValueImpl(null, 0, null, false, annotations.toPersistentList()) + +/** + * TODO + * + * @param value + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableTimeValue( + value: LocalTime, + precision: Int = 0, + offset: ZoneOffset? = null, + withZone: Boolean = false, + annotations: Annotations = emptyList(), +): NullableTimeValue = NullableTimeValueImpl(value, precision, offset, withZone, annotations.toPersistentList()) + +/** + * TODO + * + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableTimestampValue( + annotations: Annotations = emptyList(), +): NullableTimestampValue = NullableTimestampValueImpl(null, 0, null, false, annotations.toPersistentList()) + +/** + * TODO + * + * @param value + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableTimestampValue( + value: LocalDateTime, + precision: Int = 0, + offset: ZoneOffset? = null, + withZone: Boolean = false, + annotations: Annotations = emptyList(), +): NullableTimestampValue = NullableTimestampValueImpl(value, precision, offset, withZone, annotations.toPersistentList()) + +/** + * TODO + * + * @param value + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableIntervalValue( + value: Long? = null, + annotations: Annotations = emptyList(), +): NullableIntervalValue = NullableIntervalValueImpl(value, annotations.toPersistentList()) + +/** + * TODO + * + * @param T + * @param elements + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableBagValue( + elements: List? = null, + annotations: Annotations = emptyList(), +): NullableBagValue = NullableBagValueImpl(elements?.toPersistentList(), annotations.toPersistentList()) + +/** + * TODO + * + * @param T + * @param elements + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableListValue( + elements: List? = null, + annotations: Annotations = emptyList(), +): NullableListValue = NullableListValueImpl(elements?.toPersistentList(), annotations.toPersistentList()) + +/** + * TODO + * + * @param T + * @param elements + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableSexpValue( + elements: List? = null, + annotations: Annotations = emptyList(), +): NullableSexpValue = NullableSexpValueImpl(elements?.toPersistentList(), annotations.toPersistentList()) + +/** + * TODO + * + * @param T + * @param fields + * @param annotations + * @return + */ +@JvmOverloads +public fun nullableStructValue( + fields: List>? = null, + annotations: Annotations = emptyList(), +): NullableStructValue = NullableStructValueImpl(fields?.toPersistentList(), annotations.toPersistentList()) diff --git a/partiql-types/src/main/kotlin/org/partiql/value/PartiQLValue.kt b/partiql-types/src/main/kotlin/org/partiql/value/PartiQLValue.kt index f0acb4c053..14131417bc 100644 --- a/partiql-types/src/main/kotlin/org/partiql/value/PartiQLValue.kt +++ b/partiql-types/src/main/kotlin/org/partiql/value/PartiQLValue.kt @@ -20,8 +20,8 @@ import java.math.BigInteger import java.time.LocalDate import java.time.LocalDateTime import java.time.LocalTime +import java.time.ZoneOffset import java.util.BitSet -import java.util.TimeZone internal typealias Annotations = List @@ -40,17 +40,6 @@ public sealed interface PartiQLValue { public fun accept(visitor: PartiQLValueVisitor, ctx: C): R } -public abstract class NullValue : PartiQLValue { - - override val type: PartiQLValueType = PartiQLValueType.NULL - - abstract override fun copy(annotations: Annotations): NullValue - - abstract override fun withAnnotations(annotations: Annotations): NullValue - - abstract override fun withoutAnnotations(): NullValue -} - public abstract class MissingValue : PartiQLValue { override val type: PartiQLValueType = PartiQLValueType.MISSING @@ -187,6 +176,7 @@ public abstract class DecimalValue : NumericValue() { public abstract class Float32Value : ScalarValue { override val type: PartiQLValueType = PartiQLValueType.FLOAT32 + abstract override fun copy(annotations: Annotations): Float32Value abstract override fun withAnnotations(annotations: Annotations): Float32Value @@ -321,10 +311,13 @@ public abstract class TimeValue : ScalarValue { override val type: PartiQLValueType = PartiQLValueType.TIME // TEMPORARY - public abstract val timeZone: TimeZone? + public abstract val precision: Int // TEMPORARY - public abstract val precision: Int + public abstract val offset: ZoneOffset? + + // TEMPORARY + public abstract val withZone: Boolean abstract override fun copy(annotations: Annotations): TimeValue @@ -338,10 +331,13 @@ public abstract class TimestampValue : ScalarValue { override val type: PartiQLValueType = PartiQLValueType.TIMESTAMP // TEMPORARY - public abstract val timeZone: TimeZone? + public abstract val precision: Int // TEMPORARY - public abstract val precision: Int + public abstract val offset: ZoneOffset? + + // TEMPORARY + public abstract val withZone: Boolean abstract override fun copy(annotations: Annotations): TimestampValue @@ -406,20 +402,3 @@ public abstract class StructValue : PartiQLValue, Collection

} - -/** - * Any view over a PartiQLValue - */ -public abstract class AnyValue : PartiQLValue { - - public abstract val value: PartiQLValue - - override val type: PartiQLValueType - get() = value.type - - abstract override fun copy(annotations: Annotations): AnyValue - - abstract override fun withAnnotations(annotations: Annotations): AnyValue - - abstract override fun withoutAnnotations(): AnyValue -} diff --git a/partiql-types/src/main/kotlin/org/partiql/value/PartiQLValueNullable.kt b/partiql-types/src/main/kotlin/org/partiql/value/PartiQLValueNullable.kt new file mode 100644 index 0000000000..70aca65424 --- /dev/null +++ b/partiql-types/src/main/kotlin/org/partiql/value/PartiQLValueNullable.kt @@ -0,0 +1,387 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at: + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ + +package org.partiql.value + +import org.partiql.types.PartiQLValueType +import java.math.BigDecimal +import java.math.BigInteger +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime +import java.time.ZoneOffset +import java.util.BitSet + +public abstract class NullValue : PartiQLValue { + + override val type: PartiQLValueType = PartiQLValueType.NULL + + abstract override fun copy(annotations: Annotations): NullValue + + abstract override fun withAnnotations(annotations: Annotations): NullValue + + abstract override fun withoutAnnotations(): NullValue +} + +public sealed interface NullableScalarValue : PartiQLValue { + + public val value: T? + + override fun copy(annotations: Annotations): NullableScalarValue + + override fun withAnnotations(annotations: Annotations): NullableScalarValue + + override fun withoutAnnotations(): NullableScalarValue +} + +public sealed interface NullableCollectionValue : PartiQLValue, Collection { + + public override val size: Int + + public val elements: Collection? + + override fun copy(annotations: Annotations): NullableCollectionValue + + override fun withAnnotations(annotations: Annotations): NullableCollectionValue + + override fun withoutAnnotations(): NullableCollectionValue +} + +public abstract class NullableBoolValue : NullableScalarValue { + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_BOOL + + abstract override fun copy(annotations: Annotations): NullableBoolValue + + abstract override fun withAnnotations(annotations: Annotations): NullableBoolValue + + abstract override fun withoutAnnotations(): NullableBoolValue +} + +public sealed class NullableNumericValue : NullableScalarValue { + + public val int: Int? + get() = value?.toInt() + + public val long: Long? + get() = value?.toLong() + + public val float: Float? + get() = value?.toFloat() + + public val double: Double? + get() = value?.toDouble() + + abstract override fun copy(annotations: Annotations): NullableNumericValue + + abstract override fun withAnnotations(annotations: Annotations): NullableNumericValue + + abstract override fun withoutAnnotations(): NullableNumericValue +} + +public abstract class NullableInt8Value : NullableNumericValue() { + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_INT8 + + abstract override fun copy(annotations: Annotations): NullableInt8Value + + abstract override fun withAnnotations(annotations: Annotations): NullableInt8Value + + abstract override fun withoutAnnotations(): NullableInt8Value +} + +public abstract class NullableInt16Value : NullableNumericValue() { + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_INT16 + + abstract override fun copy(annotations: Annotations): NullableInt16Value + + abstract override fun withAnnotations(annotations: Annotations): NullableInt16Value + + abstract override fun withoutAnnotations(): NullableInt16Value +} + +public abstract class NullableInt32Value : NullableNumericValue() { + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_INT32 + + abstract override fun copy(annotations: Annotations): NullableInt32Value + + abstract override fun withAnnotations(annotations: Annotations): NullableInt32Value + + abstract override fun withoutAnnotations(): NullableInt32Value +} + +public abstract class NullableInt64Value : NullableNumericValue() { + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_INT64 + + abstract override fun copy(annotations: Annotations): NullableInt64Value + + abstract override fun withAnnotations(annotations: Annotations): NullableInt64Value + + abstract override fun withoutAnnotations(): NullableInt64Value +} + +public abstract class NullableIntValue : NullableNumericValue() { + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_INT + + abstract override fun copy(annotations: Annotations): NullableIntValue + + abstract override fun withAnnotations(annotations: Annotations): NullableIntValue + + abstract override fun withoutAnnotations(): NullableIntValue +} + +public abstract class NullableDecimalValue : NullableNumericValue() { + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_DECIMAL + + abstract override fun copy(annotations: Annotations): NullableDecimalValue + + abstract override fun withAnnotations(annotations: Annotations): NullableDecimalValue + + abstract override fun withoutAnnotations(): NullableDecimalValue +} + +public abstract class NullableFloat32Value : NullableScalarValue { + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_FLOAT32 + + abstract override fun copy(annotations: Annotations): NullableFloat32Value + + abstract override fun withAnnotations(annotations: Annotations): NullableFloat32Value + + abstract override fun withoutAnnotations(): NullableFloat32Value +} + +public abstract class NullableFloat64Value : NullableScalarValue { + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_FLOAT64 + + abstract override fun copy(annotations: Annotations): NullableFloat64Value + + abstract override fun withAnnotations(annotations: Annotations): NullableFloat64Value + + abstract override fun withoutAnnotations(): NullableFloat64Value +} + +public sealed class NullableTextValue : NullableScalarValue { + + public abstract val string: String? + + abstract override fun copy(annotations: Annotations): NullableTextValue + + abstract override fun withAnnotations(annotations: Annotations): NullableTextValue + + abstract override fun withoutAnnotations(): NullableTextValue +} + +public abstract class NullableCharValue : NullableTextValue() { + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_CHAR + + override val string: String? + get() = value?.toString() + + abstract override fun copy(annotations: Annotations): NullableCharValue + + abstract override fun withAnnotations(annotations: Annotations): NullableCharValue + + abstract override fun withoutAnnotations(): NullableCharValue +} + +public abstract class NullableStringValue : NullableTextValue() { + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_STRING + + override val string: String? + get() = value + + abstract override fun copy(annotations: Annotations): NullableStringValue + + abstract override fun withAnnotations(annotations: Annotations): NullableStringValue + + abstract override fun withoutAnnotations(): NullableStringValue +} + +public abstract class NullableSymbolValue : NullableTextValue() { + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_SYMBOL + + override val string: String? + get() = value + + abstract override fun copy(annotations: Annotations): NullableSymbolValue + + abstract override fun withAnnotations(annotations: Annotations): NullableSymbolValue + + abstract override fun withoutAnnotations(): NullableSymbolValue +} + +public abstract class NullableClobValue : NullableTextValue() { + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_CLOB + + override val string: String? + get() = value?.toString(Charsets.UTF_8) + + abstract override fun copy(annotations: Annotations): NullableClobValue + + abstract override fun withAnnotations(annotations: Annotations): NullableClobValue + + abstract override fun withoutAnnotations(): NullableClobValue +} + +public abstract class NullableBinaryValue : NullableScalarValue { + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_BINARY + + abstract override fun copy(annotations: Annotations): NullableBinaryValue + + abstract override fun withAnnotations(annotations: Annotations): NullableBinaryValue + + abstract override fun withoutAnnotations(): NullableBinaryValue +} + +public abstract class NullableByteValue : NullableScalarValue { + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_BYTE + + abstract override fun copy(annotations: Annotations): NullableByteValue + + abstract override fun withAnnotations(annotations: Annotations): NullableByteValue + + abstract override fun withoutAnnotations(): NullableByteValue +} + +public abstract class NullableBlobValue : NullableScalarValue { + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_BLOB + + abstract override fun copy(annotations: Annotations): NullableBlobValue + + abstract override fun withAnnotations(annotations: Annotations): NullableBlobValue + + abstract override fun withoutAnnotations(): NullableBlobValue +} + +public abstract class NullableDateValue : NullableScalarValue { + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_DATE + + abstract override fun copy(annotations: Annotations): NullableDateValue + + abstract override fun withAnnotations(annotations: Annotations): NullableDateValue + + abstract override fun withoutAnnotations(): NullableDateValue +} + +public abstract class NullableTimeValue : NullableScalarValue { + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_TIME + + // TEMPORARY + public abstract val precision: Int + + // TEMPORARY + public abstract val offset: ZoneOffset? + + // TEMPORARY + public abstract val withZone: Boolean + + abstract override fun copy(annotations: Annotations): NullableTimeValue + + abstract override fun withAnnotations(annotations: Annotations): NullableTimeValue + + abstract override fun withoutAnnotations(): NullableTimeValue +} + +public abstract class NullableTimestampValue : NullableScalarValue { + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_TIMESTAMP + + // TEMPORARY + public abstract val precision: Int + + // TEMPORARY + public abstract val offset: ZoneOffset? + + // TEMPORARY + public abstract val withZone: Boolean + + abstract override fun copy(annotations: Annotations): NullableTimestampValue + + abstract override fun withAnnotations(annotations: Annotations): NullableTimestampValue + + abstract override fun withoutAnnotations(): NullableTimestampValue +} + +public abstract class NullableIntervalValue : NullableScalarValue { + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_INTERVAL + + abstract override fun copy(annotations: Annotations): NullableIntervalValue + + abstract override fun withAnnotations(annotations: Annotations): NullableIntervalValue + + abstract override fun withoutAnnotations(): NullableIntervalValue +} + +public abstract class NullableBagValue : NullableCollectionValue { + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_BAG + + abstract override fun copy(annotations: Annotations): NullableBagValue + + abstract override fun withAnnotations(annotations: Annotations): NullableBagValue + + abstract override fun withoutAnnotations(): NullableBagValue +} + +public abstract class NullableListValue : NullableCollectionValue { + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_LIST + + abstract override fun copy(annotations: Annotations): NullableListValue + + abstract override fun withAnnotations(annotations: Annotations): NullableListValue + + abstract override fun withoutAnnotations(): NullableListValue +} + +public abstract class NullableSexpValue : NullableCollectionValue { + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_SEXP + + abstract override fun copy(annotations: Annotations): NullableSexpValue + + abstract override fun withAnnotations(annotations: Annotations): NullableSexpValue + + abstract override fun withoutAnnotations(): NullableSexpValue +} + +public abstract class NullableStructValue : PartiQLValue, Collection> { + + public abstract val fields: List>? + + override val type: PartiQLValueType = PartiQLValueType.NULLABLE_STRUCT + + abstract override fun copy(annotations: Annotations): NullableStructValue + + abstract override fun withAnnotations(annotations: Annotations): NullableStructValue + + abstract override fun withoutAnnotations(): NullableStructValue +} diff --git a/partiql-types/src/main/kotlin/org/partiql/value/PartiQLValueVisitor.kt b/partiql-types/src/main/kotlin/org/partiql/value/PartiQLValueVisitor.kt index 45669e3ab8..7f9f288bb2 100644 --- a/partiql-types/src/main/kotlin/org/partiql/value/PartiQLValueVisitor.kt +++ b/partiql-types/src/main/kotlin/org/partiql/value/PartiQLValueVisitor.kt @@ -4,10 +4,6 @@ public interface PartiQLValueVisitor { public fun visit(v: PartiQLValue, ctx: C): R - public fun visitNull(v: NullValue, ctx: C): R - - public fun visitMissing(v: MissingValue, ctx: C): R - public fun visitScalar(v: ScalarValue<*>, ctx: C): R public fun visitCollection(v: CollectionValue<*>, ctx: C): R @@ -64,7 +60,65 @@ public interface PartiQLValueVisitor { public fun visitStruct(v: StructValue<*>, ctx: C): R - public fun visitAny(v: AnyValue, ctx: C): R + public fun visitNull(v: NullValue, ctx: C): R + + public fun visitMissing(v: MissingValue, ctx: C): R + + public fun visitNullableScalar(v: NullableScalarValue<*>, ctx: C): R + + public fun visitNullableCollection(v: NullableCollectionValue<*>, ctx: C): R + + public fun visitNullableBool(v: NullableBoolValue, ctx: C): R + + public fun visitNullableNumeric(v: NullableNumericValue<*>, ctx: C): R + + public fun visitNullableInt8(v: NullableInt8Value, ctx: C): R + + public fun visitNullableInt16(v: NullableInt16Value, ctx: C): R + + public fun visitNullableInt32(v: NullableInt32Value, ctx: C): R + + public fun visitNullableInt64(v: NullableInt64Value, ctx: C): R + + public fun visitNullableInt(v: NullableIntValue, ctx: C): R + + public fun visitNullableDecimal(v: NullableDecimalValue, ctx: C): R + + public fun visitNullableFloat32(v: NullableFloat32Value, ctx: C): R + + public fun visitNullableFloat64(v: NullableFloat64Value, ctx: C): R + + public fun visitNullableText(v: NullableTextValue<*>, ctx: C): R + + public fun visitNullableChar(v: NullableCharValue, ctx: C): R + + public fun visitNullableString(v: NullableStringValue, ctx: C): R + + public fun visitNullableSymbol(v: NullableSymbolValue, ctx: C): R + + public fun visitNullableClob(v: NullableClobValue, ctx: C): R + + public fun visitNullableBinary(v: NullableBinaryValue, ctx: C): R + + public fun visitNullableByte(v: NullableByteValue, ctx: C): R + + public fun visitNullableBlob(v: NullableBlobValue, ctx: C): R + + public fun visitNullableDate(v: NullableDateValue, ctx: C): R + + public fun visitNullableTime(v: NullableTimeValue, ctx: C): R + + public fun visitNullableTimestamp(v: NullableTimestampValue, ctx: C): R + + public fun visitNullableInterval(v: NullableIntervalValue, ctx: C): R + + public fun visitNullableBag(v: NullableBagValue<*>, ctx: C): R + + public fun visitNullableList(v: NullableListValue<*>, ctx: C): R + + public fun visitNullableSexp(v: NullableSexpValue<*>, ctx: C): R + + public fun visitNullableStruct(v: NullableStructValue<*>, ctx: C): R } public abstract class PartiQLValueBaseVisitor : PartiQLValueVisitor { @@ -77,6 +131,12 @@ public abstract class PartiQLValueBaseVisitor : PartiQLValueVisitor is StructValue<*> -> { v.fields.forEach { it.second.accept(this, ctx) } } + is NullableCollectionValue<*> -> { + v.elements?.forEach { it.accept(this, ctx) } + } + is NullableStructValue<*> -> { + v.fields?.forEach { it.second.accept(this, ctx) } + } else -> {} } return defaultReturn(v, ctx) @@ -86,10 +146,6 @@ public abstract class PartiQLValueBaseVisitor : PartiQLValueVisitor override fun visit(v: PartiQLValue, ctx: C): R = v.accept(this, ctx) - override fun visitNull(v: NullValue, ctx: C): R = defaultVisit(v, ctx) - - override fun visitMissing(v: MissingValue, ctx: C): R = defaultVisit(v, ctx) - override fun visitScalar(v: ScalarValue<*>, ctx: C): R = when (v) { is BinaryValue -> visitBinary(v, ctx) is BlobValue -> visitBlob(v, ctx) @@ -183,5 +239,100 @@ public abstract class PartiQLValueBaseVisitor : PartiQLValueVisitor override fun visitStruct(v: StructValue<*>, ctx: C): R = defaultVisit(v, ctx) - override fun visitAny(v: AnyValue, ctx: C): R = v.value.accept(this, ctx) + override fun visitNull(v: NullValue, ctx: C): R = defaultVisit(v, ctx) + + override fun visitMissing(v: MissingValue, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableScalar(v: NullableScalarValue<*>, ctx: C): R = when (v) { + is NullableBinaryValue -> visitNullableBinary(v, ctx) + is NullableBlobValue -> visitNullableBlob(v, ctx) + is NullableBoolValue -> visitNullableBool(v, ctx) + is NullableByteValue -> visitNullableByte(v, ctx) + is NullableDateValue -> visitNullableDate(v, ctx) + is NullableFloat32Value -> visitNullableFloat32(v, ctx) + is NullableFloat64Value -> visitNullableFloat64(v, ctx) + is NullableIntervalValue -> visitNullableInterval(v, ctx) + is NullableDecimalValue -> visitNullableDecimal(v, ctx) + is NullableInt16Value -> visitNullableInt16(v, ctx) + is NullableInt32Value -> visitNullableInt32(v, ctx) + is NullableInt64Value -> visitNullableInt64(v, ctx) + is NullableInt8Value -> visitNullableInt8(v, ctx) + is NullableIntValue -> visitNullableInt(v, ctx) + is NullableCharValue -> visitNullableChar(v, ctx) + is NullableClobValue -> visitNullableClob(v, ctx) + is NullableStringValue -> visitNullableString(v, ctx) + is NullableSymbolValue -> visitNullableSymbol(v, ctx) + is NullableTimeValue -> visitNullableTime(v, ctx) + is NullableTimestampValue -> visitNullableTimestamp(v, ctx) + } + + override fun visitNullableCollection(v: NullableCollectionValue<*>, ctx: C): R = when (v) { + is NullableBagValue -> visitNullableBag(v, ctx) + is NullableListValue -> visitNullableList(v, ctx) + is NullableSexpValue -> visitNullableSexp(v, ctx) + } + + override fun visitNullableBool(v: NullableBoolValue, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableNumeric(v: NullableNumericValue<*>, ctx: C): R = when (v) { + is NullableDecimalValue -> visitNullableDecimal(v, ctx) + is NullableInt16Value -> visitNullableInt16(v, ctx) + is NullableInt32Value -> visitNullableInt32(v, ctx) + is NullableInt64Value -> visitNullableInt64(v, ctx) + is NullableInt8Value -> visitNullableInt8(v, ctx) + is NullableIntValue -> visitNullableInt(v, ctx) + } + + override fun visitNullableInt8(v: NullableInt8Value, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableInt16(v: NullableInt16Value, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableInt32(v: NullableInt32Value, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableInt64(v: NullableInt64Value, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableInt(v: NullableIntValue, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableDecimal(v: NullableDecimalValue, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableFloat32(v: NullableFloat32Value, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableFloat64(v: NullableFloat64Value, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableText(v: NullableTextValue<*>, ctx: C): R = when (v) { + is NullableCharValue -> visitNullableChar(v, ctx) + is NullableClobValue -> visitNullableClob(v, ctx) + is NullableStringValue -> visitNullableString(v, ctx) + is NullableSymbolValue -> visitNullableSymbol(v, ctx) + } + + override fun visitNullableChar(v: NullableCharValue, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableString(v: NullableStringValue, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableSymbol(v: NullableSymbolValue, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableClob(v: NullableClobValue, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableBinary(v: NullableBinaryValue, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableByte(v: NullableByteValue, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableBlob(v: NullableBlobValue, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableDate(v: NullableDateValue, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableTime(v: NullableTimeValue, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableTimestamp(v: NullableTimestampValue, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableInterval(v: NullableIntervalValue, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableBag(v: NullableBagValue<*>, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableList(v: NullableListValue<*>, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableSexp(v: NullableSexpValue<*>, ctx: C): R = defaultVisit(v, ctx) + + override fun visitNullableStruct(v: NullableStructValue<*>, ctx: C): R = defaultVisit(v, ctx) } diff --git a/partiql-types/src/main/kotlin/org/partiql/value/impl/PartiQLValueImpl.kt b/partiql-types/src/main/kotlin/org/partiql/value/impl/PartiQLValueImpl.kt index 7a6866f7b9..cd443154b4 100644 --- a/partiql-types/src/main/kotlin/org/partiql/value/impl/PartiQLValueImpl.kt +++ b/partiql-types/src/main/kotlin/org/partiql/value/impl/PartiQLValueImpl.kt @@ -36,8 +36,6 @@ import org.partiql.value.Int8Value import org.partiql.value.IntValue import org.partiql.value.IntervalValue import org.partiql.value.ListValue -import org.partiql.value.MissingValue -import org.partiql.value.NullValue import org.partiql.value.PartiQLValue import org.partiql.value.PartiQLValueVisitor import org.partiql.value.SexpValue @@ -51,8 +49,8 @@ import java.math.BigInteger import java.time.LocalDate import java.time.LocalDateTime import java.time.LocalTime +import java.time.ZoneOffset import java.util.BitSet -import java.util.TimeZone @Suppress("FunctionName") internal inline fun T._withAnnotations(annotations: Annotations): T = @@ -68,32 +66,6 @@ internal inline fun T._withoutAnnotations(): T = else -> this } -internal data class NullValueImpl( - override val annotations: PersistentList, -) : NullValue() { - - override fun copy(annotations: Annotations) = NullValueImpl(annotations.toPersistentList()) - - override fun withAnnotations(annotations: Annotations): NullValue = _withAnnotations(annotations) - - override fun withoutAnnotations(): NullValue = _withoutAnnotations() - - override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNull(this, ctx) -} - -internal data class MissingValueImpl( - override val annotations: PersistentList, -) : MissingValue() { - - override fun copy(annotations: Annotations) = MissingValueImpl(annotations.toPersistentList()) - - override fun withAnnotations(annotations: Annotations): MissingValue = _withAnnotations(annotations) - - override fun withoutAnnotations(): MissingValue = _withoutAnnotations() - - override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitMissing(this, ctx) -} - internal data class BoolValueImpl( override val value: Boolean, override val annotations: PersistentList, @@ -334,10 +306,11 @@ internal data class DateValueImpl( internal data class TimeValueImpl( override val value: LocalTime, override val precision: Int, - override val timeZone: TimeZone?, + override val offset: ZoneOffset?, + override val withZone: Boolean, override val annotations: PersistentList, ) : TimeValue() { - override fun copy(annotations: Annotations) = TimeValueImpl(value, precision, timeZone, annotations.toPersistentList()) + override fun copy(annotations: Annotations) = TimeValueImpl(value, precision, offset, withZone, annotations.toPersistentList()) override fun withAnnotations(annotations: Annotations): TimeValue = _withAnnotations(annotations) @@ -349,10 +322,11 @@ internal data class TimeValueImpl( internal data class TimestampValueImpl( override val value: LocalDateTime, override val precision: Int, - override val timeZone: TimeZone?, + override val offset: ZoneOffset?, + override val withZone: Boolean, override val annotations: PersistentList, ) : TimestampValue() { - override fun copy(annotations: Annotations) = TimestampValueImpl(value, precision, timeZone, annotations.toPersistentList()) + override fun copy(annotations: Annotations) = TimestampValueImpl(value, precision, offset, withZone, annotations.toPersistentList()) override fun withAnnotations(annotations: Annotations): TimestampValue = _withAnnotations(annotations) diff --git a/partiql-types/src/main/kotlin/org/partiql/value/impl/PartiQLValueNullableImpl.kt b/partiql-types/src/main/kotlin/org/partiql/value/impl/PartiQLValueNullableImpl.kt new file mode 100644 index 0000000000..f4e4287889 --- /dev/null +++ b/partiql-types/src/main/kotlin/org/partiql/value/impl/PartiQLValueNullableImpl.kt @@ -0,0 +1,496 @@ +/* + * Copyright 2022 Amazon.com, Inc. or its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at: + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ + +package org.partiql.value.impl + +import kotlinx.collections.immutable.PersistentList +import kotlinx.collections.immutable.toImmutableList +import kotlinx.collections.immutable.toPersistentList +import org.partiql.value.Annotations +import org.partiql.value.MissingValue +import org.partiql.value.NullValue +import org.partiql.value.NullableBagValue +import org.partiql.value.NullableBinaryValue +import org.partiql.value.NullableBlobValue +import org.partiql.value.NullableBoolValue +import org.partiql.value.NullableByteValue +import org.partiql.value.NullableCharValue +import org.partiql.value.NullableClobValue +import org.partiql.value.NullableDateValue +import org.partiql.value.NullableDecimalValue +import org.partiql.value.NullableFloat32Value +import org.partiql.value.NullableFloat64Value +import org.partiql.value.NullableInt16Value +import org.partiql.value.NullableInt32Value +import org.partiql.value.NullableInt64Value +import org.partiql.value.NullableInt8Value +import org.partiql.value.NullableIntValue +import org.partiql.value.NullableIntervalValue +import org.partiql.value.NullableListValue +import org.partiql.value.NullableSexpValue +import org.partiql.value.NullableStringValue +import org.partiql.value.NullableStructValue +import org.partiql.value.NullableSymbolValue +import org.partiql.value.NullableTimeValue +import org.partiql.value.NullableTimestampValue +import org.partiql.value.PartiQLValue +import org.partiql.value.PartiQLValueVisitor +import java.math.BigDecimal +import java.math.BigInteger +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime +import java.time.ZoneOffset +import java.util.BitSet + +internal data class NullValueImpl( + override val annotations: PersistentList, +) : NullValue() { + + override fun copy(annotations: Annotations) = NullValueImpl(annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullValue = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullValue = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNull(this, ctx) +} + +internal data class MissingValueImpl( + override val annotations: PersistentList, +) : MissingValue() { + + override fun copy(annotations: Annotations) = MissingValueImpl(annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): MissingValue = _withAnnotations(annotations) + + override fun withoutAnnotations(): MissingValue = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitMissing(this, ctx) +} + +internal data class NullableBoolValueImpl( + override val value: Boolean?, + override val annotations: PersistentList, +) : NullableBoolValue() { + + override fun copy(annotations: Annotations) = NullableBoolValueImpl(value, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableBoolValue = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableBoolValue = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNullableBool(this, ctx) +} + +internal data class NullableInt8ValueImpl( + override val value: Byte?, + override val annotations: PersistentList, +) : NullableInt8Value() { + + override fun copy(annotations: Annotations) = NullableInt8ValueImpl(value, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableInt8Value = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableInt8Value = _withoutAnnotations() + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNullableInt8(this, ctx) +} + +internal data class NullableInt16ValueImpl( + override val value: Short?, + override val annotations: PersistentList, +) : NullableInt16Value() { + + override fun copy(annotations: Annotations) = NullableInt16ValueImpl(value, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableInt16Value = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableInt16Value = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNullableInt16(this, ctx) +} + +internal data class NullableInt32ValueImpl( + override val value: Int?, + override val annotations: PersistentList, +) : NullableInt32Value() { + + override fun copy(annotations: Annotations) = NullableInt32ValueImpl(value, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableInt32Value = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableInt32Value = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNullableInt32(this, ctx) +} + +internal data class NullableInt64ValueImpl( + override val value: Long?, + override val annotations: PersistentList, +) : NullableInt64Value() { + override fun copy(annotations: Annotations) = NullableInt64ValueImpl(value, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableInt64Value = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableInt64Value = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNullableInt64(this, ctx) +} + +internal data class NullableIntValueImpl( + override val value: BigInteger?, + override val annotations: PersistentList, +) : NullableIntValue() { + + override fun copy(annotations: Annotations) = NullableIntValueImpl(value, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableIntValue = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableIntValue = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNullableInt(this, ctx) +} + +internal data class NullableDecimalValueImpl( + override val value: BigDecimal?, + override val annotations: PersistentList, +) : NullableDecimalValue() { + + override fun copy(annotations: Annotations) = NullableDecimalValueImpl(value, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableDecimalValue = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableDecimalValue = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNullableDecimal(this, ctx) +} + +internal data class NullableFloat32ValueImpl( + override val value: Float?, + override val annotations: PersistentList, +) : NullableFloat32Value() { + + override fun copy(annotations: Annotations) = NullableFloat32ValueImpl(value, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableFloat32Value = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableFloat32Value = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNullableFloat32(this, ctx) +} + +internal data class NullableFloat64ValueImpl( + override val value: Double?, + override val annotations: PersistentList, +) : NullableFloat64Value() { + override fun copy(annotations: Annotations) = NullableFloat64ValueImpl(value, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableFloat64Value = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableFloat64Value = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNullableFloat64(this, ctx) +} + +internal data class NullableCharValueImpl( + override val value: Char?, + override val annotations: PersistentList, +) : NullableCharValue() { + + override fun copy(annotations: Annotations) = NullableCharValueImpl(value, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableCharValue = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableCharValue = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNullableChar(this, ctx) +} + +internal data class NullableStringValueImpl( + override val value: String?, + override val annotations: PersistentList, +) : NullableStringValue() { + override fun copy(annotations: Annotations) = NullableStringValueImpl(value, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableStringValue = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableStringValue = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNullableString(this, ctx) +} + +internal data class NullableSymbolValueImpl( + override val value: String?, + override val annotations: PersistentList, +) : NullableSymbolValue() { + override fun copy(annotations: Annotations) = NullableSymbolValueImpl(value, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableSymbolValue = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableSymbolValue = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNullableSymbol(this, ctx) +} + +internal data class NullableClobValueImpl( + override val value: ByteArray?, + override val annotations: PersistentList, +) : NullableClobValue() { + override fun copy(annotations: Annotations) = NullableClobValueImpl(value, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableClobValue = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableClobValue = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNullableClob(this, ctx) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + other as NullableClobValueImpl + if (value != null) { + if (other.value == null) return false + if (!value.contentEquals(other.value)) return false + } else if (other.value != null) return false + return annotations == other.annotations + } + + override fun hashCode(): Int { + var result = value?.contentHashCode() ?: 0 + result = 31 * result + annotations.hashCode() + return result + } +} + +internal data class NullableBinaryValueImpl( + override val value: BitSet?, + override val annotations: PersistentList, +) : NullableBinaryValue() { + override fun copy(annotations: Annotations) = NullableBinaryValueImpl(value, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableBinaryValue = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableBinaryValue = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNullableBinary(this, ctx) +} + +internal data class NullableByteValueImpl( + override val value: Byte?, + override val annotations: PersistentList, +) : NullableByteValue() { + override fun copy(annotations: Annotations) = NullableByteValueImpl(value, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableByteValue = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableByteValue = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNullableByte(this, ctx) +} + +internal data class NullableBlobValueImpl( + override val value: ByteArray?, + override val annotations: PersistentList, +) : NullableBlobValue() { + + override fun copy(annotations: Annotations) = NullableBlobValueImpl(value, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableBlobValue = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableBlobValue = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNullableBlob(this, ctx) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + other as NullableClobValueImpl + if (value != null) { + if (other.value == null) return false + if (!value.contentEquals(other.value)) return false + } else if (other.value != null) return false + return annotations == other.annotations + } + + override fun hashCode(): Int { + var result = value?.contentHashCode() ?: 0 + result = 31 * result + annotations.hashCode() + return result + } +} + +internal data class NullableDateValueImpl( + override val value: LocalDate?, + override val annotations: PersistentList, +) : NullableDateValue() { + override fun copy(annotations: Annotations) = NullableDateValueImpl(value, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableDateValue = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableDateValue = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNullableDate(this, ctx) +} + +internal data class NullableTimeValueImpl( + override val value: LocalTime?, + override val precision: Int, + override val offset: ZoneOffset?, + override val withZone: Boolean, + override val annotations: PersistentList, +) : NullableTimeValue() { + override fun copy(annotations: Annotations) = + NullableTimeValueImpl(value, precision, offset, withZone, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableTimeValue = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableTimeValue = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNullableTime(this, ctx) +} + +internal data class NullableTimestampValueImpl( + override val value: LocalDateTime?, + override val precision: Int, + override val offset: ZoneOffset?, + override val withZone: Boolean, + override val annotations: PersistentList, +) : NullableTimestampValue() { + override fun copy(annotations: Annotations) = + NullableTimestampValueImpl(value, precision, offset, withZone, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableTimestampValue = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableTimestampValue = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = + visitor.visitNullableTimestamp(this, ctx) +} + +internal data class NullableIntervalValueImpl( + override val value: Long?, + override val annotations: PersistentList, +) : NullableIntervalValue() { + override fun copy(annotations: Annotations) = NullableIntervalValueImpl(value, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableIntervalValue = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableIntervalValue = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNullableInterval(this, ctx) +} + +internal data class NullableBagValueImpl( + private val delegate: PersistentList?, + override val annotations: PersistentList, +) : NullableBagValue() { + + override fun contains(element: T) = delegate!!.contains(element) + + override fun containsAll(elements: Collection) = delegate!!.containsAll(elements) + + override fun isEmpty() = delegate!!.isEmpty() + + override fun iterator() = delegate!!.iterator() + + override val size = delegate!!.size + + override val elements = delegate!!.toImmutableList() + + override fun copy(annotations: Annotations) = NullableBagValueImpl(delegate, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableBagValue = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableBagValue = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNullableBag(this, ctx) +} + +internal data class NullableListValueImpl( + private val delegate: PersistentList?, + override val annotations: PersistentList, +) : NullableListValue() { + + override fun contains(element: T) = delegate!!.contains(element) + + override fun containsAll(elements: Collection) = delegate!!.containsAll(elements) + + override fun isEmpty() = delegate!!.isEmpty() + + override fun iterator() = delegate!!.iterator() + + override val size = delegate!!.size + + override val elements = delegate!!.toImmutableList() + + override fun copy(annotations: Annotations) = NullableListValueImpl(delegate, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableListValue = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableListValue = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNullableList(this, ctx) +} + +internal data class NullableSexpValueImpl( + private val delegate: PersistentList?, + override val annotations: PersistentList, +) : NullableSexpValue() { + + override fun contains(element: T) = delegate!!.contains(element) + + override fun containsAll(elements: Collection) = delegate!!.containsAll(elements) + + override fun isEmpty() = delegate!!.isEmpty() + + override fun iterator() = delegate!!.iterator() + + override val size = delegate!!.size + + override val elements = delegate!!.toImmutableList() + + override fun copy(annotations: Annotations) = NullableSexpValueImpl(delegate, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableSexpValue = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableSexpValue = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNullableSexp(this, ctx) +} + +internal data class NullableStructValueImpl( + private val values: PersistentList>?, + override val annotations: PersistentList, +) : NullableStructValue() { + + override val fields = values!!.toImmutableList() + + override val size = values!!.size + + override fun isEmpty() = values!!.isEmpty() + + override fun iterator(): Iterator> = values!!.iterator() + + override fun containsAll(elements: Collection>) = values!!.containsAll(elements) + + override fun contains(element: Pair) = values!!.contains(element) + + override fun copy(annotations: Annotations) = NullableStructValueImpl(values, annotations.toPersistentList()) + + override fun withAnnotations(annotations: Annotations): NullableStructValue = _withAnnotations(annotations) + + override fun withoutAnnotations(): NullableStructValue = _withoutAnnotations() + + override fun accept(visitor: PartiQLValueVisitor, ctx: C): R = visitor.visitNullableStruct(this, ctx) +} diff --git a/partiql-types/src/main/kotlin/org/partiql/value/impl/PartiQLValueTextWriter.kt b/partiql-types/src/main/kotlin/org/partiql/value/impl/PartiQLValueTextWriter.kt index 9a2eaf4fef..99f2af4396 100644 --- a/partiql-types/src/main/kotlin/org/partiql/value/impl/PartiQLValueTextWriter.kt +++ b/partiql-types/src/main/kotlin/org/partiql/value/impl/PartiQLValueTextWriter.kt @@ -1,6 +1,5 @@ package org.partiql.value.impl -import org.partiql.value.AnyValue import org.partiql.value.BagValue import org.partiql.value.BoolValue import org.partiql.value.CharValue @@ -16,6 +15,22 @@ import org.partiql.value.IntValue import org.partiql.value.ListValue import org.partiql.value.MissingValue import org.partiql.value.NullValue +import org.partiql.value.NullableBagValue +import org.partiql.value.NullableBoolValue +import org.partiql.value.NullableCharValue +import org.partiql.value.NullableDecimalValue +import org.partiql.value.NullableFloat32Value +import org.partiql.value.NullableFloat64Value +import org.partiql.value.NullableInt16Value +import org.partiql.value.NullableInt32Value +import org.partiql.value.NullableInt64Value +import org.partiql.value.NullableInt8Value +import org.partiql.value.NullableIntValue +import org.partiql.value.NullableListValue +import org.partiql.value.NullableSexpValue +import org.partiql.value.NullableStringValue +import org.partiql.value.NullableStructValue +import org.partiql.value.NullableSymbolValue import org.partiql.value.PartiQLValue import org.partiql.value.PartiQLValueBaseVisitor import org.partiql.value.PartiQLValueWriter @@ -23,6 +38,22 @@ import org.partiql.value.SexpValue import org.partiql.value.StringValue import org.partiql.value.StructValue import org.partiql.value.SymbolValue +import org.partiql.value.bagValue +import org.partiql.value.boolValue +import org.partiql.value.charValue +import org.partiql.value.decimalValue +import org.partiql.value.float32Value +import org.partiql.value.float64Value +import org.partiql.value.int16Value +import org.partiql.value.int32Value +import org.partiql.value.int64Value +import org.partiql.value.int8Value +import org.partiql.value.intValue +import org.partiql.value.listValue +import org.partiql.value.sexpValue +import org.partiql.value.stringValue +import org.partiql.value.structValue +import org.partiql.value.symbolValue import java.io.PrintStream /** @@ -192,6 +223,84 @@ internal class PartiQLValueTextWriter( append("}") } - override fun visitAny(v: AnyValue, format: Format?) = v.toString(format) { "any" } + override fun visitNullableBool(v: NullableBoolValue, ctx: Format?) = when (v.value) { + null -> "null" + else -> visitBool(boolValue(v.value!!, v.annotations), ctx) + } + + override fun visitNullableInt8(v: NullableInt8Value, ctx: Format?) = when (v.value) { + null -> "null" + else -> visitInt8(int8Value(v.value!!, v.annotations), ctx) + } + + override fun visitNullableInt16(v: NullableInt16Value, ctx: Format?) = when (v.value) { + null -> "null" + else -> visitInt16(int16Value(v.value!!, v.annotations), ctx) + } + + override fun visitNullableInt32(v: NullableInt32Value, ctx: Format?) = when (v.value) { + null -> "null" + else -> visitInt32(int32Value(v.value!!, v.annotations), ctx) + } + + override fun visitNullableInt64(v: NullableInt64Value, ctx: Format?) = when (v.value) { + null -> "null" + else -> visitInt64(int64Value(v.value!!, v.annotations), ctx) + } + + override fun visitNullableInt(v: NullableIntValue, ctx: Format?) = when (v.value) { + null -> "null" + else -> visitInt(intValue(v.value!!, v.annotations), ctx) + } + + override fun visitNullableDecimal(v: NullableDecimalValue, ctx: Format?) = when (v.value) { + null -> "null" + else -> visitDecimal(decimalValue(v.value!!, v.annotations), ctx) + } + + override fun visitNullableFloat32(v: NullableFloat32Value, ctx: Format?) = when (v.value) { + null -> "null" + else -> visitFloat32(float32Value(v.value!!, v.annotations), ctx) + } + + override fun visitNullableFloat64(v: NullableFloat64Value, ctx: Format?) = when (v.value) { + null -> "null" + else -> visitFloat64(float64Value(v.value!!, v.annotations), ctx) + } + + override fun visitNullableChar(v: NullableCharValue, ctx: Format?) = when (v.value) { + null -> "null" + else -> visitChar(charValue(v.value!!, v.annotations), ctx) + } + + override fun visitNullableString(v: NullableStringValue, ctx: Format?) = when (v.value) { + null -> "null" + else -> visitString(stringValue(v.value!!, v.annotations), ctx) + } + + override fun visitNullableSymbol(v: NullableSymbolValue, ctx: Format?) = when (v.value) { + null -> "null" + else -> visitSymbol(symbolValue(v.value!!, v.annotations), ctx) + } + + override fun visitNullableBag(v: NullableBagValue<*>, ctx: Format?) = when (v.elements) { + null -> "null" + else -> visitBag(bagValue(v.elements!!.toList(), v.annotations), ctx) + } + + override fun visitNullableList(v: NullableListValue<*>, ctx: Format?) = when (v.elements) { + null -> "null" + else -> visitList(listValue(v.elements!!.toList(), v.annotations), ctx) + } + + override fun visitNullableSexp(v: NullableSexpValue<*>, ctx: Format?) = when (v.elements) { + null -> "null" + else -> visitSexp(sexpValue(v.elements!!.toList(), v.annotations), ctx) + } + + override fun visitNullableStruct(v: NullableStructValue<*>, ctx: Format?) = when (v.fields) { + null -> "null" + else -> visitStruct(structValue(v.fields!!.toList(), v.annotations), ctx) + } } } diff --git a/partiql-types/src/test/kotlin/org/partiql/value/impl/PartiQLValueTextWriterTest.kt b/partiql-types/src/test/kotlin/org/partiql/value/impl/PartiQLValueTextWriterTest.kt index 21f56ec826..84baa6b3cf 100644 --- a/partiql-types/src/test/kotlin/org/partiql/value/impl/PartiQLValueTextWriterTest.kt +++ b/partiql-types/src/test/kotlin/org/partiql/value/impl/PartiQLValueTextWriterTest.kt @@ -6,7 +6,6 @@ import org.junit.jupiter.api.parallel.ExecutionMode import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.MethodSource import org.partiql.value.Annotations -import org.partiql.value.AnyValue import org.partiql.value.PartiQLValue import org.partiql.value.bagValue import org.partiql.value.boolValue @@ -22,6 +21,18 @@ import org.partiql.value.intValue import org.partiql.value.listValue import org.partiql.value.missingValue import org.partiql.value.nullValue +import org.partiql.value.nullableBoolValue +import org.partiql.value.nullableCharValue +import org.partiql.value.nullableDecimalValue +import org.partiql.value.nullableFloat32Value +import org.partiql.value.nullableFloat64Value +import org.partiql.value.nullableInt16Value +import org.partiql.value.nullableInt32Value +import org.partiql.value.nullableInt64Value +import org.partiql.value.nullableInt8Value +import org.partiql.value.nullableIntValue +import org.partiql.value.nullableStringValue +import org.partiql.value.nullableSymbolValue import org.partiql.value.sexpValue import org.partiql.value.stringValue import org.partiql.value.structValue @@ -35,8 +46,6 @@ import java.math.BigInteger * Basic text writing test. * * TODOs - * - Annotation tests - * - Nested collections * - Dates and times * - String/Symbol escapes */ @@ -47,6 +56,11 @@ class PartiQLValueTextWriterTest { @Execution(ExecutionMode.CONCURRENT) fun testScalars(case: Case) = case.assert() + @ParameterizedTest + @MethodSource("nulls") + @Execution(ExecutionMode.CONCURRENT) + fun testNulls(case: Case) = case.assert() + @ParameterizedTest @MethodSource("collections") @Execution(ExecutionMode.CONCURRENT) @@ -177,6 +191,142 @@ class PartiQLValueTextWriterTest { // TODO INTERVAL ) + @JvmStatic + fun nulls() = listOf( + case( + value = nullValue(), + expected = "null", + ), + case( + value = missingValue(), + expected = "missing", + ), + case( + value = nullableBoolValue(true), + expected = "true", + ), + case( + value = nullableBoolValue(false), + expected = "false", + ), + case( + value = nullableBoolValue(null), + expected = "null", + ), + case( + value = nullableInt8Value(1), + expected = "1", + ), + case( + value = nullableInt8Value(null), + expected = "null", + ), + case( + value = nullableInt16Value(1), + expected = "1", + ), + case( + value = nullableInt16Value(null), + expected = "null", + ), + case( + value = nullableInt32Value(1), + expected = "1", + ), + case( + value = nullableInt32Value(null), + expected = "null", + ), + case( + value = nullableInt64Value(1), + expected = "1", + ), + case( + value = nullableInt64Value(null), + expected = "null", + ), + case( + value = nullableIntValue(BigInteger.valueOf(1)), + expected = "1", + ), + case( + value = nullableIntValue(null), + expected = "null", + ), + case( + value = nullableDecimalValue(BigDecimal("123.456")), + expected = "123.456", + ), + case( + value = nullableDecimalValue(null), + expected = "null", + ), + case( + value = nullableFloat32Value(123.0f), + expected = "123.0", + ), + case( + value = nullableFloat32Value(null), + expected = "null", + ), + case( + value = nullableFloat64Value(123.0), + expected = "123.0", + ), + case( + value = nullableFloat64Value(null), + expected = "null", + ), + case( + value = nullableCharValue('C'), + expected = "'C'", + ), + case( + value = nullableCharValue(null), + expected = "null", + ), + case( + value = nullableStringValue("word"), + expected = "'word'", + ), + case( + value = nullableStringValue(null), + expected = "null", + ), + case( + value = nullableStringValue("word\nword"), + expected = "'word\nword'", + ), + case( + value = nullableStringValue(null), + expected = "null", + ), + case( + value = nullableSymbolValue("x"), + expected = "x", + ), + case( + value = nullableSymbolValue(null), + expected = "null", + ), + case( + value = nullableSymbolValue("f.x"), + expected = "f.x", + ), + case( + value = nullableSymbolValue(null), + expected = "null", + ), + // TODO CLOB + // TODO BINARY + // TODO BYTE + // TODO BLOB + // TODO DATE + // TODO TIME + // TODO TIMESTAMP + // TODO INTERVAL + ) + @JvmStatic fun collections() = listOf( case( @@ -226,7 +376,7 @@ class PartiQLValueTextWriterTest { @JvmStatic fun struct() = listOf( case( - value = structValue(emptyList()), + value = structValue(emptyList()), expected = "{}", ), case( @@ -295,7 +445,7 @@ class PartiQLValueTextWriterTest { @JvmStatic fun structFormatted() = listOf( formatted( - value = structValue(emptyList()), + value = structValue(emptyList()), expected = "{}", ), formatted( @@ -409,9 +559,9 @@ class PartiQLValueTextWriterTest { formatted( value = structValue( listOf( - "bag" to bagValue(emptyList()), - "list" to listValue(emptyList()), - "sexp" to sexpValue(emptyList()), + "bag" to bagValue(emptyList()), + "list" to listValue(emptyList()), + "sexp" to sexpValue(emptyList()), ) ), expected = """ @@ -425,9 +575,9 @@ class PartiQLValueTextWriterTest { formatted( value = bagValue( listOf( - listValue(emptyList()), - sexpValue(emptyList()), - structValue(emptyList()), + listValue(emptyList()), + sexpValue(emptyList()), + structValue(emptyList()), ) ), expected = """