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

Adds a built-in PartiQL System catalog, support for SQL-Path, and SPI cleanup #1670

Merged
merged 13 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
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
Loading