Skip to content

Commit

Permalink
Adds DatumWriter for most types
Browse files Browse the repository at this point in the history
  • Loading branch information
RCHowell committed Dec 18, 2024
1 parent 5446de5 commit d94a4af
Show file tree
Hide file tree
Showing 11 changed files with 1,118 additions and 64 deletions.
97 changes: 97 additions & 0 deletions docs/wiki/v1/streams.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# PartiQL Data Streams

*This document defines the PSink and PSource in relation to Datum and Java primitives*

* * *

### Background

We have defined
an [encoding of PartiQL values using the Ion data format](https://quip-amazon.com/5Su8AQhKG5xA/PartiQL-Values-in-Ion),
but how does this fit in? Let’s look at two questions.

1. How does PartiQL represent values in memory?
2. How does PartiQL read values from a stream into memory?

An in-memory PartiQL value has a layer of indirection between the Java primitive and its view to the rest of the
program. This is called the “Datum” and is a fat interface which allows the partiql-lang-kotlin engine to not worry
about a value’s Java type, and instead switch on an int tag (ptype) to then pull out a value. Effectively the fat
interface removes checking classes and casting with tag checking then accessing without a cast. It’s effectively a
unifying interface over the old values, so how does the variant fit in?

A variant is an implementation of a Datum whose value is opaque to the rest of the system. When the system checks the
tag, it simply gets back “variant<T>” where T might tell us a set of capabilities (or traits) this type system / value
has. This value is not lowered into a PartiQL value such as an INT or ARRAY, but is kept in its “container” or “box”.
Think of the variant types of other engines or jsonb of PostgreSQL.

So how does PartiQL read values from a stream into Datums, and how does it handle variants? It depends because an
encoding may include a data type or it may not. Also, the reader itself may expect a type (or not). Consider that a
PartiQL value carries a type with it along with the value itself.

## Writing Data

### PSink

The PSink interface is used to write PartiQL data. It has APIs just like the IonWriter, and similarly, it has different
implementations for the actual encoding like how Ion has both a text and a binary encoding. A PSink is used without any
assumptions about the actual encoding.

### DatumWriter

The DatumWriter is a class which facilitates writing datums via a PSink implementation; it is handles materializing a
datum and calling the appropriate sink methods.

**Example**

```kotlin
val writer = DatumWriter.standard(sink)
writer.write(datum1)
writer.write(datum2)
writer.write(datum3)
writer.close()
```

### IonSink

This example shows how to encode a datum as Ion; type decorations are omitted where possible.

```kotlin
val sink = IonSink(System.out) // printing
val writer = DatumWriter(sink)

// bool
writer.write(Datum.bool(true)) // >> true

// ints
writer.write(Datum.smallint(1)) // >> smallint::1
writer.write(Datum.int(2)) // >> int::2
writer.write(Datum.bigint(3)) // >> 3

// exact and approx numeric
writer.write(Datum.decimal(BigDecimal("3.14"), 3, 2)) // >> ((decimal 3 2) 3.14)
writer.write(Datum.real(3.14f)) // >> real::3.14e0
writer.write(Datum.doublePrecision(3.14)) // >> 3.14e0

// char strings
writer.write(Datum.char("abc", 3)) // >> ((char 3) "abc")
writer.write(Datum.varchar("abc", 3)) // >> ((varchar 3) "abc")
writer.write(Datum.string("abc")) // >> "abc"

// lobs
writer.write(Datum.clob("hello".toByteArray()), 5) // >> {{ "hello" }}
writer.write(Datum.blob("hello".toByteArray()), 5) // >> {{ aGVsbG8= }}

// datetime
// TODO blocked on https://github.com/partiql/partiql-lang-kotlin/pull/1656

// ion

```

## Reading Data

### DatumReader

### PSource

PLACEHOLDER
131 changes: 129 additions & 2 deletions partiql-spi/api/partiql-spi.api
Original file line number Diff line number Diff line change
Expand Up @@ -464,8 +464,67 @@ public final class org/partiql/spi/function/Routine$DefaultImpls {
public static fun getParameters (Lorg/partiql/spi/function/Routine;)[Lorg/partiql/spi/function/Parameter;
}

public abstract interface class org/partiql/spi/stream/PSink {
public fun close ()V
public fun finish ()V
public fun flush ()V
public abstract fun setType (Lorg/partiql/types/PType;)V
public abstract fun stepIn (I)V
public abstract fun stepOut ()V
public abstract fun writeBigint (J)V
public abstract fun writeBlob ([B)V
public abstract fun writeBool (Z)V
public abstract fun writeChar (Ljava/lang/String;)V
public abstract fun writeClob ([B)V
public abstract fun writeDate (Lorg/partiql/value/datetime/Date;)V
public abstract fun writeDecimal (Ljava/math/BigDecimal;)V
public abstract fun writeDouble (D)V
public abstract fun writeField (Ljava/lang/String;)V
public abstract fun writeInt (I)V
public abstract fun writeMissing ()V
public abstract fun writeNull ()V
public abstract fun writeNumeric (Ljava/math/BigDecimal;)V
public abstract fun writeReal (F)V
public abstract fun writeSmallint (S)V
public abstract fun writeString (Ljava/lang/String;)V
public abstract fun writeTime (Lorg/partiql/value/datetime/Time;)V
public abstract fun writeTimestamp (Lorg/partiql/value/datetime/Timestamp;)V
public abstract fun writeTimestampz (Lorg/partiql/value/datetime/Timestamp;)V
public abstract fun writeTimez (Lorg/partiql/value/datetime/Time;)V
public abstract fun writeTinyint (B)V
public abstract fun writeVarchar (Ljava/lang/String;)V
public abstract fun writeVariant (Ljava/lang/Object;)V
}

public abstract interface class org/partiql/spi/stream/PSource {
public fun close ()V
public abstract fun next ()Lorg/partiql/types/PType;
public abstract fun readBigint ()J
public abstract fun readBlob ()[B
public abstract fun readBool ()Z
public abstract fun readChar ()Ljava/lang/String;
public abstract fun readClob ()[B
public abstract fun readDate ()Lorg/partiql/value/datetime/Date;
public abstract fun readDecimal ()Ljava/math/BigDecimal;
public abstract fun readDouble ()D
public abstract fun readField (Ljava/lang/String;)Ljava/lang/String;
public abstract fun readInt ()I
public abstract fun readReal ()F
public abstract fun readSmallint ()S
public abstract fun readString ()Ljava/lang/String;
public abstract fun readTime ()Lorg/partiql/value/datetime/Time;
public abstract fun readTimestamp ()Lorg/partiql/value/datetime/Timestamp;
public abstract fun readTimestampz ()Lorg/partiql/value/datetime/Timestamp;
public abstract fun readTimez ()Lorg/partiql/value/datetime/Time;
public abstract fun readTinyint ()B
public abstract fun readVarchar ()Ljava/lang/String;
public abstract fun stepIn ()V
public abstract fun stepOut ()V
}

public abstract interface class org/partiql/spi/value/Datum : java/lang/Iterable {
public static fun array (Ljava/lang/Iterable;)Lorg/partiql/spi/value/Datum;
public static fun array (Ljava/lang/Iterable;Lorg/partiql/types/PType;)Lorg/partiql/spi/value/Datum;
public static fun bag (Ljava/lang/Iterable;)Lorg/partiql/spi/value/Datum;
public static fun bigint (J)Lorg/partiql/spi/value/Datum;
public static fun blob ([B)Lorg/partiql/spi/value/Datum;
Expand Down Expand Up @@ -538,8 +597,10 @@ public class org/partiql/spi/value/DatumReader$Builder {
public fun register (Lorg/partiql/spi/value/Encoding;Lorg/partiql/spi/value/DatumReader;)Lorg/partiql/spi/value/DatumReader$Builder;
}

public abstract interface class org/partiql/spi/value/DatumWriter : java/lang/AutoCloseable {
public abstract fun write (Lorg/partiql/spi/value/Datum;)Lorg/partiql/spi/value/DatumWriter;
public final class org/partiql/spi/value/DatumWriter : java/lang/AutoCloseable {
public fun <init> (Lorg/partiql/spi/stream/PSink;)V
public fun close ()V
public final fun write (Lorg/partiql/spi/value/Datum;)V
}

public class org/partiql/spi/value/Encoding : org/partiql/spi/Enum {
Expand All @@ -555,6 +616,72 @@ public abstract interface class org/partiql/spi/value/Field {
public static fun of (Ljava/lang/String;Lorg/partiql/spi/value/Datum;)Lorg/partiql/spi/value/Field;
}

public final class org/partiql/spi/value/ion/IonSink : org/partiql/spi/stream/PSink {
public static final field Companion Lorg/partiql/spi/value/ion/IonSink$Companion;
public fun <init> (Lcom/amazon/ion/IonWriter;Ljava/util/BitSet;)V
public static final fun binary (Ljava/io/OutputStream;)Lorg/partiql/spi/value/ion/IonSink;
public static final fun binary (Ljava/io/OutputStream;[I)Lorg/partiql/spi/value/ion/IonSink;
public fun close ()V
public static final fun decorated ()Lorg/partiql/spi/value/ion/IonSink$Builder;
public static final fun elided ()Lorg/partiql/spi/value/ion/IonSink$Builder;
public fun finish ()V
public fun flush ()V
public static final fun pretty (Ljava/lang/Appendable;)Lorg/partiql/spi/value/ion/IonSink;
public static final fun pretty (Ljava/lang/Appendable;[I)Lorg/partiql/spi/value/ion/IonSink;
public fun setType (Lorg/partiql/types/PType;)V
public static final fun standard ()Lorg/partiql/spi/value/ion/IonSink$Builder;
public static final fun standard (Lcom/amazon/ion/IonWriter;)Lorg/partiql/spi/value/ion/IonSink;
public fun stepIn (I)V
public fun stepOut ()V
public static final fun text (Ljava/lang/Appendable;)Lorg/partiql/spi/value/ion/IonSink;
public static final fun text (Ljava/lang/Appendable;[I)Lorg/partiql/spi/value/ion/IonSink;
public fun writeBigint (J)V
public fun writeBlob ([B)V
public fun writeBool (Z)V
public fun writeChar (Ljava/lang/String;)V
public fun writeClob ([B)V
public fun writeDate (Lorg/partiql/value/datetime/Date;)V
public fun writeDecimal (Ljava/math/BigDecimal;)V
public fun writeDouble (D)V
public fun writeField (Ljava/lang/String;)V
public fun writeInt (I)V
public fun writeMissing ()V
public fun writeNull ()V
public fun writeNumeric (Ljava/math/BigDecimal;)V
public fun writeReal (F)V
public fun writeSmallint (S)V
public fun writeString (Ljava/lang/String;)V
public fun writeTime (Lorg/partiql/value/datetime/Time;)V
public fun writeTimestamp (Lorg/partiql/value/datetime/Timestamp;)V
public fun writeTimestampz (Lorg/partiql/value/datetime/Timestamp;)V
public fun writeTimez (Lorg/partiql/value/datetime/Time;)V
public fun writeTinyint (B)V
public fun writeVarchar (Ljava/lang/String;)V
public fun writeVariant (Ljava/lang/Object;)V
}

public final class org/partiql/spi/value/ion/IonSink$Builder {
public final fun build (Lcom/amazon/ion/IonWriter;)Lorg/partiql/spi/value/ion/IonSink;
public final fun decorate (I)Lorg/partiql/spi/value/ion/IonSink$Builder;
public final fun elide (I)Lorg/partiql/spi/value/ion/IonSink$Builder;
}

public final class org/partiql/spi/value/ion/IonSink$Companion {
public final fun binary (Ljava/io/OutputStream;)Lorg/partiql/spi/value/ion/IonSink;
public final fun binary (Ljava/io/OutputStream;[I)Lorg/partiql/spi/value/ion/IonSink;
public static synthetic fun binary$default (Lorg/partiql/spi/value/ion/IonSink$Companion;Ljava/io/OutputStream;[IILjava/lang/Object;)Lorg/partiql/spi/value/ion/IonSink;
public final fun decorated ()Lorg/partiql/spi/value/ion/IonSink$Builder;
public final fun elided ()Lorg/partiql/spi/value/ion/IonSink$Builder;
public final fun pretty (Ljava/lang/Appendable;)Lorg/partiql/spi/value/ion/IonSink;
public final fun pretty (Ljava/lang/Appendable;[I)Lorg/partiql/spi/value/ion/IonSink;
public static synthetic fun pretty$default (Lorg/partiql/spi/value/ion/IonSink$Companion;Ljava/lang/Appendable;[IILjava/lang/Object;)Lorg/partiql/spi/value/ion/IonSink;
public final fun standard ()Lorg/partiql/spi/value/ion/IonSink$Builder;
public final fun standard (Lcom/amazon/ion/IonWriter;)Lorg/partiql/spi/value/ion/IonSink;
public final fun text (Ljava/lang/Appendable;)Lorg/partiql/spi/value/ion/IonSink;
public final fun text (Ljava/lang/Appendable;[I)Lorg/partiql/spi/value/ion/IonSink;
public static synthetic fun text$default (Lorg/partiql/spi/value/ion/IonSink$Companion;Ljava/lang/Appendable;[IILjava/lang/Object;)Lorg/partiql/spi/value/ion/IonSink;
}

public abstract class org/partiql/value/BagValue : org/partiql/value/CollectionValue {
public fun <init> ()V
public abstract fun copy (Ljava/util/List;)Lorg/partiql/value/BagValue;
Expand Down
Loading

0 comments on commit d94a4af

Please sign in to comment.