Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initializes PartiQLCursor and PartiQLValueLoader #1467

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions partiql-eval/api/partiql-eval.api
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ public final class org/partiql/eval/PartiQLResult$Error : org/partiql/eval/Parti
}

public final class org/partiql/eval/PartiQLResult$Value : org/partiql/eval/PartiQLResult {
public fun <init> (Lorg/partiql/value/PartiQLValue;)V
public final fun component1 ()Lorg/partiql/value/PartiQLValue;
public final fun copy (Lorg/partiql/value/PartiQLValue;)Lorg/partiql/eval/PartiQLResult$Value;
public static synthetic fun copy$default (Lorg/partiql/eval/PartiQLResult$Value;Lorg/partiql/value/PartiQLValue;ILjava/lang/Object;)Lorg/partiql/eval/PartiQLResult$Value;
public fun <init> (Lorg/partiql/value/PartiQLCursor;)V
public final fun component1 ()Lorg/partiql/value/PartiQLCursor;
public final fun copy (Lorg/partiql/value/PartiQLCursor;)Lorg/partiql/eval/PartiQLResult$Value;
public static synthetic fun copy$default (Lorg/partiql/eval/PartiQLResult$Value;Lorg/partiql/value/PartiQLCursor;ILjava/lang/Object;)Lorg/partiql/eval/PartiQLResult$Value;
public fun equals (Ljava/lang/Object;)Z
public final fun getValue ()Lorg/partiql/value/PartiQLValue;
public final fun getCursor ()Lorg/partiql/value/PartiQLCursor;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import org.partiql.eval.internal.Compiler
import org.partiql.eval.internal.Environment
import org.partiql.eval.internal.Symbols
import org.partiql.plan.PartiQLPlan
import org.partiql.value.PartiQLCursor
import org.partiql.value.PartiQLValue
import org.partiql.value.PartiQLValueExperimental

Expand Down Expand Up @@ -33,7 +34,8 @@ internal class PartiQLEngineDefault : PartiQLEngine {
return when (statement) {
is PartiQLStatement.Query -> try {
val value = statement.execute()
PartiQLResult.Value(value)
val data = PartiQLCursor.of(value)
PartiQLResult.Value(data)
} catch (ex: Exception) {
PartiQLResult.Error(ex)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package org.partiql.eval

import org.partiql.value.PartiQLValue
import org.partiql.value.PartiQLCursor
import org.partiql.value.PartiQLValueExperimental

public sealed interface PartiQLResult {

@OptIn(PartiQLValueExperimental::class)
public data class Value(public val value: PartiQLValue) : PartiQLResult
public data class Value(public val cursor: PartiQLCursor) : PartiQLResult

public data class Error(public val cause: Throwable) : PartiQLResult
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.MethodSource
import org.partiql.eval.PartiQLEngine
import org.partiql.eval.PartiQLResult
import org.partiql.eval.internal.PartiQLEngineDefaultTest.SuccessTestCase.Global
import org.partiql.parser.PartiQLParser
import org.partiql.plan.PartiQLPlan
import org.partiql.plan.debug.PlanPrinter
Expand All @@ -22,6 +21,7 @@ import org.partiql.types.StaticType
import org.partiql.value.CollectionValue
import org.partiql.value.PartiQLValue
import org.partiql.value.PartiQLValueExperimental
import org.partiql.value.PartiQLValueLoader
import org.partiql.value.bagValue
import org.partiql.value.boolValue
import org.partiql.value.decimalValue
Expand Down Expand Up @@ -1176,7 +1176,7 @@ class PartiQLEngineDefaultTest {
throw returned.cause
}
}
val output = result.value
val output = PartiQLValueLoader.standard().load(result.cursor)
assert(expected == output) {
comparisonString(expected, output, plan.plan)
}
Expand Down Expand Up @@ -1245,7 +1245,7 @@ class PartiQLEngineDefaultTest {
val plan = planner.plan(statement, session)
val prepared = engine.prepare(plan.plan, PartiQLEngine.Session(mapOf("memory" to connector), mode = mode))
when (val result = engine.execute(prepared)) {
is PartiQLResult.Value -> return result.value to plan.plan
is PartiQLResult.Value -> return PartiQLValueLoader.standard().load(result.cursor) to plan.plan
is PartiQLResult.Error -> throw result.cause
}
}
Expand Down
31 changes: 31 additions & 0 deletions partiql-types/api/partiql-types.api
Original file line number Diff line number Diff line change
Expand Up @@ -1108,6 +1108,32 @@ public final class org/partiql/value/PartiQL {
public static synthetic fun timestampValue$default (Lorg/partiql/value/datetime/Timestamp;Ljava/util/List;ILjava/lang/Object;)Lorg/partiql/value/TimestampValue;
}

public abstract interface class org/partiql/value/PartiQLCursor : java/lang/AutoCloseable, java/util/Iterator {
public abstract fun getBigDecimal ()Ljava/math/BigDecimal;
public abstract fun getBigInteger ()Ljava/math/BigInteger;
public abstract fun getBlob ()Ljava/sql/Blob;
public abstract fun getBoolean ()Z
public abstract fun getByte ()B
public abstract fun getBytes ()[B
public abstract fun getClob ()Ljava/sql/Clob;
public abstract fun getDate ()Lorg/partiql/value/datetime/Date;
public abstract fun getDouble ()D
public abstract fun getFieldName ()Ljava/lang/String;
public abstract fun getFloat ()F
public abstract fun getInt ()I
public abstract fun getLong ()J
public abstract fun getShort ()S
public abstract fun getString ()Ljava/lang/String;
public abstract fun getTime ()Lorg/partiql/value/datetime/Time;
public abstract fun getTimestamp ()Lorg/partiql/value/datetime/Timestamp;
public abstract fun getType ()Lorg/partiql/value/PartiQLValueType;
public abstract fun isMissing ()Z
public abstract fun isNull ()Z
public static fun of (Lorg/partiql/value/PartiQLValue;)Lorg/partiql/value/PartiQLCursor;
public abstract fun stepIn ()V
public abstract fun stepOut ()V
}

public abstract interface annotation class org/partiql/value/PartiQLTimestampExperimental : java/lang/annotation/Annotation {
}

Expand Down Expand Up @@ -1141,6 +1167,11 @@ public final class org/partiql/value/PartiQLValueKt {
public static final fun toIon (Lorg/partiql/value/PartiQLValue;)Lcom/amazon/ionelement/api/IonElement;
}

public abstract interface class org/partiql/value/PartiQLValueLoader {
public abstract fun load (Lorg/partiql/value/PartiQLCursor;)Lorg/partiql/value/PartiQLValue;
public static fun standard ()Lorg/partiql/value/PartiQLValueLoader;
}

public final class org/partiql/value/PartiQLValueType : java/lang/Enum {
public static final field ANY Lorg/partiql/value/PartiQLValueType;
public static final field BAG Lorg/partiql/value/PartiQLValueType;
Expand Down
9 changes: 9 additions & 0 deletions partiql-types/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ dependencies {
implementation(Deps.kotlinxCollections)
}

// Need to add this as we have both Java and Kotlin sources. Dokka already handles multi-language projects. If
// Javadoc is enabled, we end up overwriting index.html (causing compilation errors).
tasks.withType<Javadoc>() {
enabled = false
}
tasks.withType<Jar>() {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}

publish {
artifactId = "partiql-types"
name = "PartiQL Types"
Expand Down
250 changes: 250 additions & 0 deletions partiql-types/src/main/java/org/partiql/value/PartiQLCursor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
package org.partiql.value;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Blob;
import java.sql.Clob;
import java.util.Iterator;
import org.jetbrains.annotations.NotNull;
import org.partiql.value.datetime.Date;
import org.partiql.value.datetime.Time;
import org.partiql.value.datetime.Timestamp;

/**
* Data representing a database result set, which is usually generated by executing a statement that queries the database.
* <p>
* A {@link PartiQLCursor} object maintains a cursor pointing to its current position in the underlying data. Initially the
* cursor is positioned before the first value. The {@link #next()} method moves the cursor to the next value. Please use
* {@link #hasNext()} before calling {@link #next()}.
*
* @see PartiQLValueLoader#load(PartiQLCursor)
* @see PartiQLValue
*/
public interface PartiQLCursor extends AutoCloseable, Iterator<PartiQLValueType> {

/**
* Positions the reader just before the contents of the current value, which must be a container (list, bag,
* sexp, or struct). There's no current value immediately after stepping in, so the next thing you'll want to do is call
* {@link #hasNext()} and {@link #next()} to move onto the first child value.
* <p>
* If the container itself is the null value, stepIn() shall fail. Please use {@link #isNull()} before
* invoking this.
* <p>
* At any time {@link #stepOut()} may be called to move the cursor back to (just after) the parent value, even if
* there are more children remaining.
*/
public void stepIn() throws UnsupportedOperationException, NullPointerException;

/**
* Positions the iterator after the current parent's value, moving up one level in the data hierarchy. There's no
* current value immediately after stepping out, so the next thing you'll want to do is call {@link #hasNext()} and
* {@link #next()} to move onto the following value.
*/
public void stepOut() throws UnsupportedOperationException, NullPointerException;

/**
* Determines whether the current value is a null value of any type (for example, null or null.int). It should be
* called before calling getters that return value types (int, long, boolean, double).
*/
public boolean isNull();

/**
* Determines whether the current value is the missing value. Similarly, one can invoke {@link #getType()}.
*/
public boolean isMissing();

/**
* @return the type of the data at the cursor.
*/
@NotNull
public PartiQLValueType getType();

/**
* @return the field name of the current value; or null if there is no valid current value or if the current value
* is not a field of a struct.
*/
public String getFieldName();

/**
* This is applicable to the following types:
* {@link PartiQLValueType#STRING},
* {@link PartiQLValueType#SYMBOL},
* {@link PartiQLValueType#CHAR}
* @return a value representing the applicable PartiQL value
* @throws UnsupportedOperationException when this method is not applicable to the type returned by {@link PartiQLCursor#getType()}
* @throws NullPointerException if this method is invoked when {@link PartiQLCursor#isNull()} returns true
*/
@NotNull
String getString() throws UnsupportedOperationException, NullPointerException;

/**
* This is applicable to the following types:
* {@link PartiQLValueType#BOOL}
* @return a value representing the applicable PartiQL value
* @throws UnsupportedOperationException when this method is not applicable to the type returned by {@link PartiQLCursor#getType()}
* @throws NullPointerException if this method is invoked when {@link PartiQLCursor#isNull()} returns true
*/
public boolean getBoolean() throws UnsupportedOperationException, NullPointerException;

/**
* This is applicable to the following types:
* {@link PartiQLValueType#BINARY}
* @return a value representing the applicable PartiQL value
* @throws UnsupportedOperationException when this method is not applicable to the type returned by {@link PartiQLCursor#getType()}
* @throws NullPointerException if this method is invoked when {@link PartiQLCursor#isNull()} returns true
* @apiNote <b>! ! ! EXPERIMENTAL ! ! !</b> This is an experimental API under development by the PartiQL maintainers.
* Please abstain from using this API until given notice otherwise. This may break between iterations without prior notice.
* @deprecated BINARY doesn't exist in SQL or Ion. This is subject to deletion.
*/
@Deprecated
@NotNull
public byte[] getBytes() throws UnsupportedOperationException, NullPointerException;

/**
* This is applicable to the following types:
* {@link PartiQLValueType#BLOB}
* @return a value representing the applicable PartiQL value
* @throws UnsupportedOperationException when this method is not applicable to the type returned by {@link PartiQLCursor#getType()}
* @throws NullPointerException if this method is invoked when {@link PartiQLCursor#isNull()} returns true
* @apiNote <b>! ! ! EXPERIMENTAL ! ! !</b> This is an experimental API under development by the PartiQL maintainers.
* Please abstain from using this API until given notice otherwise. This may break between iterations without prior notice.
*/
@NotNull
public Blob getBlob() throws UnsupportedOperationException, NullPointerException;

/**
* This is applicable to the following types:
* {@link PartiQLValueType#CLOB}
* @return a value representing the applicable PartiQL value
* @throws UnsupportedOperationException when this method is not applicable to the type returned by {@link PartiQLCursor#getType()}
* @throws NullPointerException if this method is invoked when {@link PartiQLCursor#isNull()} returns true
* @apiNote <b>! ! ! EXPERIMENTAL ! ! !</b> This is an experimental API under development by the PartiQL maintainers.
* Please abstain from using this API until given notice otherwise. This may break between iterations without prior notice.
*/
@NotNull
public Clob getClob() throws UnsupportedOperationException, NullPointerException;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure these are necessary considering you can use getBytes(). I would remove them for the time being so this package has to java.sql dependency.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK. Just updated to remove for now.


/**
* This is applicable to the following types:
* {@link PartiQLValueType#BYTE},
* {@link PartiQLValueType#INT8}
* @return a value representing the applicable PartiQL value
* @throws UnsupportedOperationException when this method is not applicable to the type returned by {@link PartiQLCursor#getType()}
* @throws NullPointerException if this method is invoked when {@link PartiQLCursor#isNull()} returns true
* @apiNote <b>! ! ! EXPERIMENTAL ! ! !</b> This is an experimental API under development by the PartiQL maintainers.
* Please abstain from using this API until given notice otherwise. This may break between iterations without prior notice.
* @deprecated BYTE is not present in SQL or Ion. This is subject to deletion.
*/
@Deprecated
public byte getByte() throws UnsupportedOperationException, NullPointerException;

/**
* This is applicable to the following types:
* {@link PartiQLValueType#DATE}
* @return a value representing the applicable PartiQL value
* @throws UnsupportedOperationException when this method is not applicable to the type returned by {@link PartiQLCursor#getType()}
* @throws NullPointerException if this method is invoked when {@link PartiQLCursor#isNull()} returns true
*/
@NotNull
public Date getDate() throws UnsupportedOperationException, NullPointerException;

/**
* This is applicable to the following types:
* {@link PartiQLValueType#TIME}
* @return a value representing the applicable PartiQL value
* @throws UnsupportedOperationException when this method is not applicable to the type returned by {@link PartiQLCursor#getType()}
* @throws NullPointerException if this method is invoked when {@link PartiQLCursor#isNull()} returns true
*/
@NotNull
public Time getTime() throws UnsupportedOperationException, NullPointerException;

/**
* This is applicable to the following types:
* {@link PartiQLValueType#TIMESTAMP}
* @return a value representing the applicable PartiQL value
* @throws UnsupportedOperationException when this method is not applicable to the type returned by {@link PartiQLCursor#getType()}
* @throws NullPointerException if this method is invoked when {@link PartiQLCursor#isNull()} returns true
*/
@NotNull
public Timestamp getTimestamp() throws UnsupportedOperationException, NullPointerException;

/**
* This is applicable to the following types:
* {@link PartiQLValueType#INT16}
* @return a value representing the applicable PartiQL value
* @throws UnsupportedOperationException when this method is not applicable to the type returned by {@link PartiQLCursor#getType()}
* @throws NullPointerException if this method is invoked when {@link PartiQLCursor#isNull()} returns true
*/
public short getShort() throws UnsupportedOperationException, NullPointerException;

/**
* This is applicable to the following types:
* {@link PartiQLValueType#INT32}
* @return a value representing the applicable PartiQL value
* @throws UnsupportedOperationException when this method is not applicable to the type returned by {@link PartiQLCursor#getType()}
* @throws NullPointerException if this method is invoked when {@link PartiQLCursor#isNull()} returns true
*/
public int getInt() throws UnsupportedOperationException, NullPointerException;

/**
* This is applicable to the following types:
* {@link PartiQLValueType#INT64},
* {@link PartiQLValueType#INTERVAL}
* @return a value representing the applicable PartiQL value
* @throws UnsupportedOperationException when this method is not applicable to the type returned by {@link PartiQLCursor#getType()}
* @throws NullPointerException if this method is invoked when {@link PartiQLCursor#isNull()} returns true
* @apiNote <b>! ! ! EXPERIMENTAL ! ! !</b> This is an experimental API under development by the PartiQL maintainers.
* Please abstain from using this API until given notice otherwise. This may break between iterations without prior notice.
*/
// TODO: Internal note: This is WRONG for INTERVAL. Though, it already exists as such, therefore, this propagates
// this weird behavior. Eventually, we'll need to add real support for INTERVAL.
public long getLong() throws UnsupportedOperationException, NullPointerException;

/**
* This is applicable to the following types:
* {@link PartiQLValueType#INT}
* @return a value representing the applicable PartiQL value
* @throws UnsupportedOperationException when this method is not applicable to the type returned by {@link PartiQLCursor#getType()}
* @throws NullPointerException if this method is invoked when {@link PartiQLCursor#isNull()} returns true
* @apiNote <b>! ! ! EXPERIMENTAL ! ! !</b> This is an experimental API under development by the PartiQL maintainers.
* Please abstain from using this API until given notice otherwise. This may break between iterations without prior notice.
*/
@NotNull
public BigInteger getBigInteger() throws UnsupportedOperationException, NullPointerException;

/**
* This is applicable to the following types:
* {@link PartiQLValueType#FLOAT32}
* @return a value representing the applicable PartiQL value
* @throws UnsupportedOperationException when this method is not applicable to the type returned by {@link PartiQLCursor#getType()}
* @throws NullPointerException if this method is invoked when {@link PartiQLCursor#isNull()} returns true
*/
public float getFloat() throws UnsupportedOperationException, NullPointerException;

/**
* This is applicable to the following types:
* {@link PartiQLValueType#FLOAT64}
* @return a value representing the applicable PartiQL value
* @throws UnsupportedOperationException when this method is not applicable to the type returned by {@link PartiQLCursor#getType()}
* @throws NullPointerException if this method is invoked when {@link PartiQLCursor#isNull()} returns true
*/
public double getDouble() throws UnsupportedOperationException, NullPointerException;

/**
* This is applicable to the following types:
* {@link PartiQLValueType#DECIMAL},
* {@link PartiQLValueType#DECIMAL_ARBITRARY}
* @return a value representing the applicable PartiQL value
* @throws UnsupportedOperationException when this method is not applicable to the type returned by {@link PartiQLCursor#getType()}
* @throws NullPointerException if this method is invoked when {@link PartiQLCursor#isNull()} returns true
*/
@NotNull
public BigDecimal getBigDecimal() throws UnsupportedOperationException, NullPointerException;

/**
* Converts a {@link PartiQLValue} into {@link PartiQLCursor}.
*/
static PartiQLCursor of(PartiQLValue value) {
return new PartiQLCursorDefault(value);
}
}
Loading
Loading