-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initializes 'beam' for type and plan serde
- Loading branch information
Showing
10 changed files
with
2,429 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
174 changes: 174 additions & 0 deletions
174
partiql-types/src/main/kotlin/org/partiql/beam/BeamStatic.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
package org.partiql.beam | ||
|
||
import org.partiql.beam.io.Beam | ||
import org.partiql.types.AnyOfType | ||
import org.partiql.types.AnyType | ||
import org.partiql.types.BagType | ||
import org.partiql.types.BlobType | ||
import org.partiql.types.BoolType | ||
import org.partiql.types.ClobType | ||
import org.partiql.types.DateType | ||
import org.partiql.types.DecimalType | ||
import org.partiql.types.FloatType | ||
import org.partiql.types.IntType | ||
import org.partiql.types.ListType | ||
import org.partiql.types.MissingType | ||
import org.partiql.types.NullType | ||
import org.partiql.types.NumberConstraint | ||
import org.partiql.types.SexpType | ||
import org.partiql.types.StaticType | ||
import org.partiql.types.StringType | ||
import org.partiql.types.StructType | ||
import org.partiql.types.SymbolType | ||
import org.partiql.types.TimeType | ||
import org.partiql.types.TimestampType | ||
import org.partiql.types.TupleConstraint | ||
import org.partiql.value.PartiQLTimestampExperimental | ||
|
||
/** | ||
* Convert a static type to a Beam Shape for serde purposes. | ||
*/ | ||
public fun StaticType.beam(): Beam.Shape = when (this) { | ||
is AnyOfType -> beam() | ||
is AnyType -> Beam.Shape.TDynamic | ||
is BlobType -> Beam.Shape.TBlob | ||
is BoolType -> Beam.Shape.TBool | ||
is ClobType -> Beam.Shape.TClob | ||
is BagType -> beam() | ||
is ListType -> beam() | ||
is SexpType -> beam() | ||
is DateType -> Beam.Shape.TDate | ||
is DecimalType -> beam() | ||
is FloatType -> beam() | ||
is IntType -> beam() | ||
MissingType -> Beam.Shape.TMissing | ||
is NullType -> Beam.Shape.TNull | ||
is StringType -> beam() | ||
is StructType -> beam() | ||
is SymbolType -> Beam.Shape.TSymbol | ||
is TimeType -> beam() | ||
is TimestampType -> beam() | ||
else -> error("unsupported type $this") // graph | ||
} | ||
|
||
private fun AnyOfType.beam(): Beam.Shape.TUnion { | ||
val shapes = ArrayList<Beam.Shape>() | ||
// create some predictable ordering | ||
val sorted = this.types.sortedWith { t1, t2 -> t1::class.java.simpleName.compareTo(t2::class.java.simpleName) } | ||
for (type in sorted) { | ||
shapes.add(type.beam()) | ||
} | ||
return Beam.Shape.TUnion(Beam.Shapes(shapes)) | ||
} | ||
|
||
private fun BagType.beam(): Beam.Shape.TBag { | ||
return Beam.Shape.TBag(this.elementType.beam()) | ||
} | ||
|
||
private fun ListType.beam(): Beam.Shape.TList { | ||
return Beam.Shape.TList(this.elementType.beam()) | ||
} | ||
|
||
private fun SexpType.beam(): Beam.Shape.TSexp { | ||
return Beam.Shape.TSexp(this.elementType.beam()) | ||
} | ||
|
||
private fun DecimalType.beam(): Beam.Shape { | ||
return when (precisionScaleConstraint) { | ||
is DecimalType.PrecisionScaleConstraint.Unconstrained -> { | ||
Beam.Shape.TDecimal | ||
} | ||
is DecimalType.PrecisionScaleConstraint.Constrained -> { | ||
val p = precisionScaleConstraint.precision.toLong() | ||
val s = precisionScaleConstraint.scale.toLong() | ||
Beam.Shape.TNumeric(p, s) | ||
} | ||
} | ||
} | ||
|
||
private fun FloatType.beam(): Beam.Shape { | ||
// StaticType does not have float constraints. | ||
return Beam.Shape.TFloat64 | ||
} | ||
|
||
private fun IntType.beam(): Beam.Shape { | ||
return when (this.rangeConstraint) { | ||
IntType.IntRangeConstraint.SHORT -> Beam.Shape.TInt16 | ||
IntType.IntRangeConstraint.INT4 -> Beam.Shape.TInt32 | ||
IntType.IntRangeConstraint.LONG -> Beam.Shape.TInt64 | ||
IntType.IntRangeConstraint.UNCONSTRAINED -> Beam.Shape.TInteger | ||
} | ||
} | ||
|
||
private fun StringType.beam(): Beam.Shape { | ||
return when (lengthConstraint) { | ||
is StringType.StringLengthConstraint.Constrained -> { | ||
when (lengthConstraint.length) { | ||
is NumberConstraint.Equals -> Beam.Shape.TCharFixed(lengthConstraint.length.value.toLong()) | ||
is NumberConstraint.UpTo -> Beam.Shape.TCharVarying(lengthConstraint.length.value.toLong()) | ||
} | ||
} | ||
is StringType.StringLengthConstraint.Unconstrained -> Beam.Shape.TString | ||
} | ||
} | ||
|
||
private fun StructType.beam(): Beam.Shape.TStruct { | ||
var isClosed = false | ||
var isOrdered = false | ||
var hasUniqueKeys = false | ||
var fields = ArrayList<Beam.Field>() | ||
for (field in this.fields) { | ||
fields.add( | ||
Beam.Field( | ||
name = field.key, | ||
shape = field.value.beam(), | ||
) | ||
) | ||
} | ||
for (constraint in constraints) { | ||
when (constraint) { | ||
is TupleConstraint.Open -> isClosed = true | ||
is TupleConstraint.Ordered -> isOrdered = true | ||
is TupleConstraint.UniqueAttrs -> hasUniqueKeys = true | ||
} | ||
} | ||
return Beam.Shape.TStruct( | ||
isClosed = isClosed, | ||
isOrdered = isOrdered, | ||
hasUniqueFields = hasUniqueKeys, | ||
fields = Beam.Fields(fields), | ||
) | ||
} | ||
|
||
private fun TimeType.beam(): Beam.Shape { | ||
if (precision == null) { | ||
error("Time precision is required") | ||
} | ||
return when (withTimeZone) { | ||
true -> Beam.Shape.TTime( | ||
precision = precision.toLong(), | ||
) | ||
else -> Beam.Shape.TTimeTz( | ||
precision = precision.toLong(), | ||
offsetHour = 0L, | ||
offsetMinute = 0L, | ||
) | ||
} | ||
} | ||
|
||
@OptIn(PartiQLTimestampExperimental::class) | ||
private fun TimestampType.beam(): Beam.Shape { | ||
if (precision == null) { | ||
error("Time precision is required") | ||
} | ||
return when (withTimeZone) { | ||
true -> Beam.Shape.TTime( | ||
precision = precision.toLong(), | ||
) | ||
else -> Beam.Shape.TTimeTz( | ||
precision = precision.toLong(), | ||
offsetHour = 0L, | ||
offsetMinute = 0L, | ||
) | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
partiql-types/src/main/kotlin/org/partiql/beam/README.adoc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
= PartiQL Beam | ||
|
||
PartiQL shape and plan encodings. | ||
|
||
== Usage | ||
|
||
[source,kotlin] | ||
---- | ||
// toString | ||
val example = Shape.TNumeric(38, 0) | ||
println(example) | ||
// Output: | ||
// 'shape.numeric'::{ | ||
// precision: 38, | ||
// scale: 0 | ||
// } | ||
// write | ||
val writer = BeamWriter.text(out) | ||
writer.write(example) // base | ||
writer.writeShapeTNumeric(example) // concrete | ||
// read | ||
// similar to writer, ignore for now | ||
---- |
113 changes: 113 additions & 0 deletions
113
partiql-types/src/main/kotlin/org/partiql/beam/beam.ridl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
// PartiQL Shapes | ||
type shape union { | ||
|
||
// Bool type | ||
t_bool: unit, | ||
|
||
// Exact-numeric types | ||
t_int8: unit, | ||
t_int16: unit, | ||
t_int32: unit, | ||
t_int64: unit, | ||
t_integer: unit, // Ion int | ||
t_decimal: unit, // Ion decimal | ||
t_numeric: struct { | ||
precision: int, | ||
scale: int, | ||
}, | ||
|
||
// Approximate-numeric types | ||
t_float32: unit, | ||
t_float64: unit, | ||
t_float: struct { precision: int }, | ||
|
||
// Character String Shapes | ||
t_char_fixed: struct { | ||
length: int, | ||
}, | ||
t_char_varying: struct { | ||
length: int, | ||
}, | ||
t_string: unit, | ||
t_symbol: unit, | ||
t_clob: unit, | ||
|
||
// Bit String Shapes | ||
t_bit_fixed: struct { | ||
length: int, | ||
}, | ||
t_bit_varying: struct { | ||
length: int, | ||
}, | ||
|
||
// Byte String Shapes | ||
t_binary: unit, | ||
t_byte_fixed: struct { | ||
length: int, | ||
}, | ||
t_byte_varying: struct { | ||
length: int, | ||
}, | ||
t_blob: unit, | ||
|
||
// Date/Time Shapes | ||
t_date: unit, | ||
t_time: struct { | ||
precision: int, | ||
}, | ||
t_time_tz: struct { | ||
precision: int, | ||
offset_hour: int, | ||
offset_minute: int, | ||
}, | ||
t_timestamp: struct { | ||
precision: int, | ||
}, | ||
t_timestamp_tz: struct { | ||
precision: int, | ||
offset_hour: int, | ||
offset_minute: int, | ||
}, | ||
|
||
// Collection Shapes | ||
t_bag: struct { | ||
items: shape, | ||
}, | ||
t_list: struct { | ||
items: shape, | ||
}, | ||
t_sexp: struct { | ||
items: shape, | ||
}, | ||
|
||
// Struct Shape (currently assuming open/closed/ordered) | ||
t_struct: struct { | ||
fields: fields, | ||
is_closed: bool, | ||
is_ordered: bool, | ||
has_unique_fields: bool, | ||
}, | ||
|
||
// Absent Shapes | ||
t_null: unit, | ||
t_missing: unit, | ||
|
||
// Union Shape | ||
t_union: struct { | ||
shapes: shapes, | ||
}, | ||
|
||
// Dynamic shape | ||
t_dynamic: unit, | ||
}; | ||
|
||
type shapes shape[]; | ||
|
||
type fields field[]; | ||
|
||
type field struct { | ||
name: string, | ||
shape: shape, | ||
}; | ||
|
||
// Plans to follow |
Oops, something went wrong.