Skip to content

Commit

Permalink
Updates SPI per pull #1332
Browse files Browse the repository at this point in the history
  • Loading branch information
RCHowell committed Jan 5, 2024
1 parent dd43328 commit 00b017c
Show file tree
Hide file tree
Showing 17 changed files with 167 additions and 102 deletions.
1 change: 0 additions & 1 deletion partiql-spi/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ plugins {
}

dependencies {
api(Deps.ionElement)
api(project(":partiql-types"))
}

Expand Down
11 changes: 7 additions & 4 deletions partiql-spi/src/main/kotlin/org/partiql/spi/BindingName.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@ package org.partiql.spi
/**
* Encapsulates the data necessary to perform a binding lookup.
*/
public data class BindingName(val name: String, val bindingCase: BindingCase) {
val loweredName: String by lazy(LazyThreadSafetyMode.PUBLICATION) { name.lowercase() }
public data class BindingName(
public val name: String,
public val case: BindingCase,
) {

/**
* Compares [name] to [otherName] using the rules specified by [bindingCase].
* Compares [name] to [otherName] using the rules specified by [case].
*/
public fun isEquivalentTo(otherName: String?): Boolean = otherName != null && name.isBindingNameEquivalent(otherName, bindingCase)
public fun isEquivalentTo(otherName: String?): Boolean =
otherName != null && name.isBindingNameEquivalent(otherName, case)

/**
* Compares this string to [other] using the rules specified by [case].
Expand Down
9 changes: 6 additions & 3 deletions partiql-spi/src/main/kotlin/org/partiql/spi/BindingPath.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@

package org.partiql.spi

public data class BindingPath(
val steps: List<BindingName>
)
/**
* A [BindingPath] represents an SQL-qualified identifier which is composed of case-sensitive and case-insensitive steps.
*
* @property steps
*/
public data class BindingPath(public val steps: List<BindingName>)
10 changes: 1 addition & 9 deletions partiql-spi/src/main/kotlin/org/partiql/spi/Plugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,14 @@
package org.partiql.spi

import org.partiql.spi.connector.Connector
import org.partiql.spi.function.PartiQLFunction
import org.partiql.spi.function.PartiQLFunctionExperimental

/**
* A singular unit of external logic.
* A plugin provides a [Connector] implementation for a catalog of the PartiQL system.
*/
public interface Plugin {

/**
* A [Connector.Factory] is used to instantiate a connector.
*/
public val factory: Connector.Factory

/**
* Functions defined by this plugin.
*/
@PartiQLFunctionExperimental
public val functions: List<PartiQLFunction>
}
19 changes: 15 additions & 4 deletions partiql-spi/src/main/kotlin/org/partiql/spi/connector/Connector.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@

package org.partiql.spi.connector

import com.amazon.ionelement.api.StructElement
import org.partiql.value.PartiQLValue
import org.partiql.value.PartiQLValueExperimental
import org.partiql.value.StructValue

/**
* A mechanism by which PartiQL can access a Catalog.
Expand All @@ -37,6 +39,14 @@ public interface Connector {
*/
public fun getBindings(): ConnectorBindings

/**
* Returns a [ConnectorFunctions] which the engine uses to load user-defined-function implementations.
*
* @return
*/
@OptIn(ConnectorFunctionExperimental::class)
public fun getFunctions(): ConnectorFunctions

/**
* A Plugin leverages a [Factory] to produce a [Connector] which is used for catalog metadata and data access.
*/
Expand All @@ -50,10 +60,11 @@ public interface Connector {
/**
* The connector factory method.
*
* @param catalogName
* @param config
* @param catalogName The name of the catalog to be backed by this [Connector] instance.
* @param config Configuration
* @return
*/
public fun create(catalogName: String, config: StructElement? = null): Connector
@OptIn(PartiQLValueExperimental::class)
public fun create(catalogName: String, config: StructValue<PartiQLValue>? = null): Connector
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,17 @@ package org.partiql.spi.connector
import org.partiql.value.PartiQLValue
import org.partiql.value.PartiQLValueExperimental

/**
* [ConnectorBindings] is responsible for managing value bindings in a catalog.
*/
@OptIn(PartiQLValueExperimental::class)
public interface ConnectorBindings {

public fun getValue(path: ConnectorObjectPath): PartiQLValue
/**
* Retrieves a value for the given handle.
*
* @param handle
* @return
*/
public fun getValue(handle: ConnectorObjectHandle): PartiQLValue
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package org.partiql.spi.function
package org.partiql.spi.connector

import org.partiql.types.function.FunctionSignature
import org.partiql.value.PartiQLValue
import org.partiql.value.PartiQLValueExperimental

/**
* The [PartiQLFunction] interface is used to implement user-defined-functions (UDFs).
* The [ConnectorFunction] interface is used to implement user-defined-functions (UDFs).
* UDFs can be registered to a plugin for use in the query planner and evaluator.
*/
@PartiQLFunctionExperimental
public sealed interface PartiQLFunction {
@ConnectorFunctionExperimental
public sealed interface ConnectorFunction {

/**
* Defines the function's parameters and argument handling.
Expand All @@ -19,7 +19,7 @@ public sealed interface PartiQLFunction {
/**
* Represents an SQL row-value expression call.
*/
public interface Scalar : PartiQLFunction {
public interface Scalar : ConnectorFunction {

/**
* Scalar function signature.
Expand All @@ -39,7 +39,7 @@ public sealed interface PartiQLFunction {
/**
* Represents an SQL table-value expression call.
*/
public interface Aggregation : PartiQLFunction {
public interface Aggregation : ConnectorFunction {

/**
* Aggregation function signature.
Expand Down Expand Up @@ -73,4 +73,4 @@ public sealed interface PartiQLFunction {
@OptIn(PartiQLValueExperimental::class)
public fun value(): PartiQLValue
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.partiql.spi.connector

@RequiresOptIn(
message = "ConnectorFunction requires explicit opt-in",
level = RequiresOptIn.Level.ERROR,
)
public annotation class ConnectorFunctionExperimental
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.partiql.spi.connector

import org.partiql.types.function.FunctionSignature

/**
* A [ConnectorFunctionHandle] represents the location and typing information for a [ConnectorFunction].
*/
public sealed interface ConnectorFunctionHandle {

/**
* The absolute path to this function's definition in the catalog.
*/
public val path: ConnectorPath

/**
* The function's type definition.
*/
public val signature: FunctionSignature

/**
* Handle to a scalar function.
*
* @property path
* @property signature
*/
public data class Scalar(
override val path: ConnectorPath,
override val signature: FunctionSignature.Scalar,
) : ConnectorFunctionHandle

/**
* Handle to an aggregation function.
*
* @property path
* @property signature
*/
public data class Aggregation(
override val path: ConnectorPath,
override val signature: FunctionSignature.Aggregation,
) : ConnectorFunctionHandle
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,12 @@
package org.partiql.spi.connector

import org.partiql.types.function.FunctionSignature

/**
* ConnectorFunctions holds the function signatures for a catalogs builtins.
* A [ConnectorFunctions] implementation is responsible for linking a handle to a function implementation for execution.
*/
public abstract class ConnectorFunctions {

/**
* Scalar function signatures available via call syntax.
*/
public open val functions: List<FunctionSignature.Scalar> = emptyList()
@ConnectorFunctionExperimental
public interface ConnectorFunctions {

/**
* Scalar function signatures available via operator or special form syntax.
*/
public open val operators: List<FunctionSignature.Scalar> = emptyList()
public fun getScalarFunction(handle: ConnectorFunctionHandle.Scalar): ConnectorFunction.Scalar

/**
* Aggregation function signatures.
*/
public open val aggregations: List<FunctionSignature.Aggregation> = emptyList()
public fun getAggregationFunction(handle: ConnectorFunctionHandle.Aggregation): ConnectorFunction.Aggregation
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,37 +15,66 @@
package org.partiql.spi.connector

import org.partiql.spi.BindingPath
import org.partiql.types.StaticType

/**
* Aids in retrieving relevant Catalog metadata for the purpose of planning and execution.
*/
public interface ConnectorMetadata {

/**
* A reference to this catalog's function signatures.
*/
public val functions: ConnectorFunctions?

/**
* Returns the descriptor of an object. If the handle is unable to produce a [StaticType], implementers should
* return null.
*/
public fun getObjectType(session: ConnectorSession, handle: ConnectorObjectHandle): StaticType?

/**
* Given a [BindingPath], returns a [ConnectorObjectHandle] that corresponds to the longest-available requested path.
* For example, given an object named "Object" located within Catalog "AWS" and Namespace "a".b"."c", a user could
* call [getObjectHandle] with the [path] of "a"."b"."c"."Object". The returned [ConnectorObjectHandle] will contain
* call [getObject] with the [path] of "a"."b"."c"."Object". The returned [ConnectorObjectHandle] will contain
* the object representation and the matching path: "a"."b"."c"."Object"
*
* As another example, consider an object within a Namespace that may be a Struct with nested attributes. A user could
* call [getObjectHandle] with the [path] of "a"."b"."c"."Object"."x". In the Namespace, only object "Object" exists.
* call [getObject] with the [path] of "a"."b"."c"."Object"."x". In the Namespace, only object "Object" exists.
* Therefore, this method will return a [ConnectorObjectHandle] with the "Object" representation and the matching
* path: "a"."b"."c"."Object". The returned [ConnectorObjectHandle.absolutePath] must be correct for correct
* path: "a"."b"."c"."Object". The returned [ConnectorObjectHandle.path] must be correct for correct
* evaluation.
*
* If the [path] does not correspond to an existing [ConnectorObject], implementers should return null.
* If the [path] does not correspond to an existing [ConnectorObjectType], implementers should return null.
*/
public fun getObject(path: BindingPath): ConnectorObjectHandle?

/**
* Returns all matching scalar functions (potentially overloaded) at the given path.
* For example, if the [path] is `catalog.schema.foo`, and `foo` has two implementations, this should return both implementations in any order. If it only has a single implementation, this should return a list containing the single implementation.
* If there is not a matching function, return an empty list.
*
* @param path : the [BindingPath] that ends with a function's name. Example: `catalog.schema.foo` where `foo` is the function name.
* @return
*/
public fun getScalarFunctions(path: BindingPath): List<ConnectorFunctionHandle.Scalar>

/**
* Returns a list of scalar operators at the given path.
*
* @param path
* @return
*/
public fun getScalarOperators(path: BindingPath): List<ConnectorFunctionHandle.Scalar>

/**
* Returns a list of aggregation functions at the given path.
*
* @param path
* @return
*/
public fun getObjectHandle(session: ConnectorSession, path: BindingPath): ConnectorObjectHandle?
public fun getAggregationFunctions(path: BindingPath): List<ConnectorFunctionHandle.Aggregation>

/**
* A base implementation of ConnectorMetadata for use in Java as the generated interface DefaultImpls is final.
*/
public abstract class Base : ConnectorMetadata {

override fun getScalarFunctions(path: BindingPath): List<ConnectorFunctionHandle.Scalar> =
emptyList()

override fun getScalarOperators(path: BindingPath): List<ConnectorFunctionHandle.Scalar> =
emptyList()

override fun getAggregationFunctions(path: BindingPath): List<ConnectorFunctionHandle.Aggregation> =
emptyList()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@
package org.partiql.spi.connector

/**
* Holds a PartiQL Value's representation within a Catalog and its location within the Catalog.
* Holds a Catalog and its location within the Catalog.
*
* @property path The absolute path to this object in the catalog
* @property type Arbitrary type metadata associated with this object.
*/
public class ConnectorObjectHandle(
public val absolutePath: ConnectorObjectPath,
public val value: ConnectorObject
public data class ConnectorObjectHandle(
public val path: ConnectorPath,
public val type: ConnectorObjectType,
)
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,18 @@

package org.partiql.spi.connector

import org.partiql.types.StaticType

/**
* An object's representation within a Catalog. This is used by plugin implementers to store logic in relation to the
* [ConnectorMetadata]. An example implementation of [ConnectorObject] could represent an object of a Catalog that holds
* the serialized [org.partiql.types.StaticType], so that the [ConnectorMetadata] may be able
* to grab the descriptor using [ConnectorMetadata.getObjectType].
* [ConnectorMetadata]. An example implementation of [ConnectorObjectType] could represent an object of a Catalog that holds
* the serialized [org.partiql.types.StaticType].
*/
public interface ConnectorObject
public interface ConnectorObjectType {

/**
* Returns the descriptor of an object. If the handle is unable to produce a [StaticType], implementers should
* return null.
*/
public fun toStaticType(): StaticType?
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,4 @@ package org.partiql.spi.connector
/**
* The path to an object within the current Catalog.
*/
public data class ConnectorObjectPath(
val steps: List<String>
)
public data class ConnectorPath(public val steps: List<String>)
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ package org.partiql.spi.connector
* Session details that are exposed to plugin implementers.
*/
public interface ConnectorSession {
public fun getQueryId(): String
public fun getUserId(): String
public val queryId: String
public val userId: String
}
Loading

0 comments on commit 00b017c

Please sign in to comment.