Skip to content

Commit

Permalink
Merge pull request #1670 from johnedquinn/v1-spi
Browse files Browse the repository at this point in the history
Adds a built-in PartiQL System catalog, support for SQL-Path, and SPI cleanup
  • Loading branch information
johnedquinn authored Dec 10, 2024
2 parents 7b818d6 + 8d9ded8 commit 01ed70a
Show file tree
Hide file tree
Showing 13 changed files with 122 additions and 60 deletions.
6 changes: 2 additions & 4 deletions .github/workflows/benchmark-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@

name: JMH Benchmarks (Main)

on:
push:
branches:
- main
# TODO: Make this run on pushes to main once appropriate benchmarks have been written.
on: [workflow_dispatch]

env:
JMH_RESULTS_PATH_FROM_ROOT: partiql-lang/build/reports/jmh/results.json
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ internal class Env(private val session: Session) {
// 1. Search in current catalog and namespace
var catalog = default
var path = resolve(identifier)
var table = catalog.getTable(session, path)
var table = catalog.resolveTable(session, path)?.let { catalog.getTable(session, it) }

// 2. Lookup as a schema-qualified identifier.
if (table == null && identifier.hasQualifier()) {
path = identifier
table = catalog.getTable(session, path)
table = catalog.resolveTable(session, path)?.let { catalog.getTable(session, it) }
}

// 3. Lookup as a catalog-qualified identifier
Expand All @@ -73,7 +73,7 @@ internal class Env(private val session: Session) {
val tail = parts.drop(1)
catalog = catalogs.getCatalog(head.getText(), ignoreCase = head.isRegular()) ?: return null
path = Identifier.of(tail)
table = catalog.getTable(session, path)
table = catalog.resolveTable(session, path)?.let { catalog.getTable(session, it) }
}

// !! NOT FOUND !!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,19 @@ public class TestCatalog private constructor(
override fun getName(): String = name

override fun getTable(session: Session, name: Name): Table? {
return null
var curr: Tree = root
for (part in name) {
curr = curr.get(Identifier.delimited(part).first()) ?: break
}
return curr.table
}

override fun getTable(session: Session, identifier: Identifier): Table? {
override fun resolveTable(session: Session, identifier: Identifier): Name? {
var curr: Tree = root
for (part in identifier) {
curr = curr.get(part) ?: break
}
return curr.table
return curr.table?.getName()
}

private class Tree(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class LocalCatalog internal constructor(
/**
* TODO this doesn't handle ambiguous binding errors or back-tracking for longest prefix searching.
*/
override fun getTable(session: Session, identifier: Identifier): Table? {
override fun resolveTable(session: Session, identifier: Identifier): Name? {
val matched = mutableListOf<String>()
var curr = root
for (part in identifier) {
Expand All @@ -62,8 +62,7 @@ public class LocalCatalog internal constructor(
return null
}
// Remove the extension
val name = Name.of(matched)
return LocalTable(name, path)
return Name.of(matched)
}

// TODO preserving this logic if catalog regains the listing APIs.
Expand Down
29 changes: 14 additions & 15 deletions partiql-spi/api/partiql-spi.api
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ public abstract interface class org/partiql/spi/catalog/Catalog {
public abstract fun getAggregations (Lorg/partiql/spi/catalog/Session;Ljava/lang/String;)Ljava/util/Collection;
public abstract fun getFunctions (Lorg/partiql/spi/catalog/Session;Ljava/lang/String;)Ljava/util/Collection;
public abstract fun getName ()Ljava/lang/String;
public abstract fun getTable (Lorg/partiql/spi/catalog/Session;Lorg/partiql/spi/catalog/Identifier;)Lorg/partiql/spi/catalog/Table;
public abstract fun getTable (Lorg/partiql/spi/catalog/Session;Lorg/partiql/spi/catalog/Name;)Lorg/partiql/spi/catalog/Table;
public abstract fun resolveTable (Lorg/partiql/spi/catalog/Session;Lorg/partiql/spi/catalog/Identifier;)Lorg/partiql/spi/catalog/Name;
}

public final class org/partiql/spi/catalog/Catalog$Builder {
Expand All @@ -90,14 +90,13 @@ public final class org/partiql/spi/catalog/Catalog$Companion {
public final class org/partiql/spi/catalog/Catalog$DefaultImpls {
public static fun getAggregations (Lorg/partiql/spi/catalog/Catalog;Lorg/partiql/spi/catalog/Session;Ljava/lang/String;)Ljava/util/Collection;
public static fun getFunctions (Lorg/partiql/spi/catalog/Catalog;Lorg/partiql/spi/catalog/Session;Ljava/lang/String;)Ljava/util/Collection;
public static fun getTable (Lorg/partiql/spi/catalog/Catalog;Lorg/partiql/spi/catalog/Session;Lorg/partiql/spi/catalog/Identifier;)Lorg/partiql/spi/catalog/Table;
public static fun getTable (Lorg/partiql/spi/catalog/Catalog;Lorg/partiql/spi/catalog/Session;Lorg/partiql/spi/catalog/Name;)Lorg/partiql/spi/catalog/Table;
public static fun resolveTable (Lorg/partiql/spi/catalog/Catalog;Lorg/partiql/spi/catalog/Session;Lorg/partiql/spi/catalog/Identifier;)Lorg/partiql/spi/catalog/Name;
}

public abstract interface class org/partiql/spi/catalog/Catalogs {
public static final field Companion Lorg/partiql/spi/catalog/Catalogs$Companion;
public static fun builder ()Lorg/partiql/spi/catalog/Catalogs$Builder;
public static fun empty ()Lorg/partiql/spi/catalog/Catalogs;
public abstract fun getCatalog (Ljava/lang/String;Z)Lorg/partiql/spi/catalog/Catalog;
public static fun of (Ljava/util/Collection;)Lorg/partiql/spi/catalog/Catalogs;
public static fun of ([Lorg/partiql/spi/catalog/Catalog;)Lorg/partiql/spi/catalog/Catalogs;
Expand All @@ -111,7 +110,6 @@ public final class org/partiql/spi/catalog/Catalogs$Builder {

public final class org/partiql/spi/catalog/Catalogs$Companion {
public final fun builder ()Lorg/partiql/spi/catalog/Catalogs$Builder;
public final fun empty ()Lorg/partiql/spi/catalog/Catalogs;
public final fun of (Ljava/util/Collection;)Lorg/partiql/spi/catalog/Catalogs;
public final fun of ([Lorg/partiql/spi/catalog/Catalog;)Lorg/partiql/spi/catalog/Catalogs;
}
Expand All @@ -126,7 +124,7 @@ public final class org/partiql/spi/catalog/Identifier : java/lang/Iterable, kotl
public final fun append (Lorg/partiql/spi/catalog/Identifier;)Lorg/partiql/spi/catalog/Identifier;
public final fun append ([Lorg/partiql/spi/catalog/Identifier$Part;)Lorg/partiql/spi/catalog/Identifier;
public static final fun delimited (Ljava/lang/String;)Lorg/partiql/spi/catalog/Identifier;
public static final fun delimited (Ljava/util/Collection;)Lorg/partiql/spi/catalog/Identifier;
public static final fun delimited (Ljava/util/List;)Lorg/partiql/spi/catalog/Identifier;
public static final fun delimited ([Ljava/lang/String;)Lorg/partiql/spi/catalog/Identifier;
public fun equals (Ljava/lang/Object;)Z
public fun forEach (Ljava/util/function/Consumer;)V
Expand All @@ -138,23 +136,23 @@ public final class org/partiql/spi/catalog/Identifier : java/lang/Iterable, kotl
public fun iterator ()Ljava/util/Iterator;
public final fun matches (Ljava/lang/String;Z)Z
public static synthetic fun matches$default (Lorg/partiql/spi/catalog/Identifier;Ljava/lang/String;ZILjava/lang/Object;)Z
public static final fun of (Ljava/util/Collection;)Lorg/partiql/spi/catalog/Identifier;
public static final fun of (Ljava/util/List;)Lorg/partiql/spi/catalog/Identifier;
public static final fun of ([Lorg/partiql/spi/catalog/Identifier$Part;)Lorg/partiql/spi/catalog/Identifier;
public static final fun regular (Ljava/lang/String;)Lorg/partiql/spi/catalog/Identifier;
public static final fun regular (Ljava/util/Collection;)Lorg/partiql/spi/catalog/Identifier;
public static final fun regular (Ljava/util/List;)Lorg/partiql/spi/catalog/Identifier;
public static final fun regular ([Ljava/lang/String;)Lorg/partiql/spi/catalog/Identifier;
public fun spliterator ()Ljava/util/Spliterator;
public fun toString ()Ljava/lang/String;
}

public final class org/partiql/spi/catalog/Identifier$Companion {
public final fun delimited (Ljava/lang/String;)Lorg/partiql/spi/catalog/Identifier;
public final fun delimited (Ljava/util/Collection;)Lorg/partiql/spi/catalog/Identifier;
public final fun delimited (Ljava/util/List;)Lorg/partiql/spi/catalog/Identifier;
public final fun delimited ([Ljava/lang/String;)Lorg/partiql/spi/catalog/Identifier;
public final fun of (Ljava/util/Collection;)Lorg/partiql/spi/catalog/Identifier;
public final fun of (Ljava/util/List;)Lorg/partiql/spi/catalog/Identifier;
public final fun of ([Lorg/partiql/spi/catalog/Identifier$Part;)Lorg/partiql/spi/catalog/Identifier;
public final fun regular (Ljava/lang/String;)Lorg/partiql/spi/catalog/Identifier;
public final fun regular (Ljava/util/Collection;)Lorg/partiql/spi/catalog/Identifier;
public final fun regular (Ljava/util/List;)Lorg/partiql/spi/catalog/Identifier;
public final fun regular ([Ljava/lang/String;)Lorg/partiql/spi/catalog/Identifier;
}

Expand Down Expand Up @@ -186,14 +184,14 @@ public final class org/partiql/spi/catalog/Name : java/lang/Iterable, kotlin/jvm
public final fun hasNamespace ()Z
public fun hashCode ()I
public fun iterator ()Ljava/util/Iterator;
public static final fun of (Ljava/util/Collection;)Lorg/partiql/spi/catalog/Name;
public static final fun of (Ljava/util/List;)Lorg/partiql/spi/catalog/Name;
public static final fun of ([Ljava/lang/String;)Lorg/partiql/spi/catalog/Name;
public fun spliterator ()Ljava/util/Spliterator;
public fun toString ()Ljava/lang/String;
}

public final class org/partiql/spi/catalog/Name$Companion {
public final fun of (Ljava/util/Collection;)Lorg/partiql/spi/catalog/Name;
public final fun of (Ljava/util/List;)Lorg/partiql/spi/catalog/Name;
public final fun of ([Ljava/lang/String;)Lorg/partiql/spi/catalog/Name;
}

Expand All @@ -210,15 +208,15 @@ public final class org/partiql/spi/catalog/Namespace : java/lang/Iterable, kotli
public fun hashCode ()I
public final fun isEmpty ()Z
public fun iterator ()Ljava/util/Iterator;
public static final fun of (Ljava/util/Collection;)Lorg/partiql/spi/catalog/Namespace;
public static final fun of (Ljava/util/List;)Lorg/partiql/spi/catalog/Namespace;
public static final fun of ([Ljava/lang/String;)Lorg/partiql/spi/catalog/Namespace;
public fun spliterator ()Ljava/util/Spliterator;
public fun toString ()Ljava/lang/String;
}

public final class org/partiql/spi/catalog/Namespace$Companion {
public final fun empty ()Lorg/partiql/spi/catalog/Namespace;
public final fun of (Ljava/util/Collection;)Lorg/partiql/spi/catalog/Namespace;
public final fun of (Ljava/util/List;)Lorg/partiql/spi/catalog/Namespace;
public final fun of ([Ljava/lang/String;)Lorg/partiql/spi/catalog/Namespace;
}

Expand Down Expand Up @@ -257,10 +255,11 @@ public final class org/partiql/spi/catalog/Session$Builder {
public final fun catalog (Ljava/lang/String;)Lorg/partiql/spi/catalog/Session$Builder;
public final fun catalogs ([Lorg/partiql/spi/catalog/Catalog;)Lorg/partiql/spi/catalog/Session$Builder;
public final fun identity (Ljava/lang/String;)Lorg/partiql/spi/catalog/Session$Builder;
public final fun namespace (Ljava/util/Collection;)Lorg/partiql/spi/catalog/Session$Builder;
public final fun namespace (Ljava/util/List;)Lorg/partiql/spi/catalog/Session$Builder;
public final fun namespace (Lorg/partiql/spi/catalog/Namespace;)Lorg/partiql/spi/catalog/Session$Builder;
public final fun namespace ([Ljava/lang/String;)Lorg/partiql/spi/catalog/Session$Builder;
public final fun property (Ljava/lang/String;Ljava/lang/String;)Lorg/partiql/spi/catalog/Session$Builder;
public final fun system (Lorg/partiql/spi/catalog/Catalog;)Lorg/partiql/spi/catalog/Session$Builder;
}

public final class org/partiql/spi/catalog/Session$Companion {
Expand Down
60 changes: 60 additions & 0 deletions partiql-spi/src/main/java/org/partiql/spi/catalog/System.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.partiql.spi.catalog;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.partiql.spi.function.Aggregation;
import org.partiql.spi.function.Builtins;
import org.partiql.spi.function.Function;

import java.util.Collection;

/**
* <p>
* This package-private class implements the PartiQL System Catalog.
* </p>
* <p>
* It provides the implementation for the PartiQL System Catalog, which is a built-in catalog
* that provides access to the PartiQL language and its built-in functions and aggregations.
* </p>
* @see Session.Builder
*/
final class System implements Catalog {

@NotNull
private static final String NAME = "$system";

/**
* This is a package-private singleton.
*/
static System INSTANCE = new System();

@NotNull
@Override
public String getName() {
return NAME;
}

@Nullable
@Override
public Table getTable(@NotNull Session session, @NotNull Name name) {
return null;
}

@Nullable
@Override
public Name resolveTable(@NotNull Session session, @NotNull Identifier identifier) {
return null;
}

@NotNull
@Override
public Collection<Function> getFunctions(@NotNull Session session, @NotNull String name) {
return Builtins.INSTANCE.getFunctions(name);
}

@NotNull
@Override
public Collection<Aggregation> getAggregations(@NotNull Session session, @NotNull String name) {
return Builtins.INSTANCE.getAggregations(name);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public interface Catalog {
* 2. Invoke getTable("a"."b"."c"."Example"."x")
* 3. The implementation MUST match "a"."b"."c"."Example" to a.b.c.Example (note "x" does not match a table)
*/
public fun getTable(session: Session, identifier: Identifier): Table? = null
public fun resolveTable(session: Session, identifier: Identifier): Name? = null

/**
* Returns a collection of scalar functions in this catalog with the given name, or an empty list if none.
Expand Down
14 changes: 0 additions & 14 deletions partiql-spi/src/main/kotlin/org/partiql/spi/catalog/Catalogs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,6 @@ public interface Catalogs {
return builder().apply { catalogs.forEach { add(it) } }.build()
}

/**
* A catalog provider that always returns an empty catalog.
*/
@JvmStatic
public fun empty(): Catalogs = object : Catalogs {
private val EMPTY = object : Catalog {
override fun getName(): String = "empty"
override fun getTable(session: Session, name: Name): Table? = null
override fun getTable(session: Session, identifier: Identifier): Table? = null
}

override fun getCatalog(name: String, ignoreCase: Boolean): Catalog = EMPTY
}

@JvmStatic
public fun builder(): Builder = Builder()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class Identifier private constructor(
public fun hasQualifier(): Boolean = qualifier.isNotEmpty()

/**
* Returns a collection of the identifier parts.
* Returns an ordered collection of the identifier parts.
*/
public fun getParts(): List<Part> {
return listOf(*qualifier) + identifier
Expand Down Expand Up @@ -195,7 +195,7 @@ public class Identifier private constructor(
public fun regular(vararg parts: String): Identifier = regular(parts.toList())

@JvmStatic
public fun regular(parts: Collection<String>): Identifier {
public fun regular(parts: List<String>): Identifier {
if (parts.isEmpty()) {
error("Cannot create an identifier with no parts")
}
Expand All @@ -211,7 +211,7 @@ public class Identifier private constructor(
public fun delimited(vararg parts: String): Identifier = delimited(parts.toList())

@JvmStatic
public fun delimited(parts: Collection<String>): Identifier {
public fun delimited(parts: List<String>): Identifier {
if (parts.isEmpty()) {
error("Cannot create an identifier with no parts")
}
Expand All @@ -224,7 +224,7 @@ public class Identifier private constructor(
public fun of(vararg parts: Part): Identifier = of(parts.toList())

@JvmStatic
public fun of(parts: Collection<Part>): Identifier {
public fun of(parts: List<Part>): Identifier {
if (parts.isEmpty()) {
error("Cannot create an identifier with no parts")
}
Expand Down
4 changes: 2 additions & 2 deletions partiql-spi/src/main/kotlin/org/partiql/spi/catalog/Name.kt
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ public class Name(
public fun of(vararg names: String): Name = of(names.toList())

/**
* Construct a name from a collection of strings.
* Construct a name from an ordered collection of strings.
*/
@JvmStatic
public fun of(names: Collection<String>): Name {
public fun of(names: List<String>): Name {
assert(names.size > 0) { "Cannot create an empty name" }
val namespace = Namespace.of(names.take(names.size - 1))
val name = names.last()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public class Namespace private constructor(
}

@JvmStatic
public fun of(levels: Collection<String>): Namespace {
public fun of(levels: List<String>): Namespace {
if (levels.isEmpty()) {
return empty()
}
Expand Down
Loading

0 comments on commit 01ed70a

Please sign in to comment.