From e31dee8e5b9801f3ca60837bbd7c1984ab295dd2 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Fri, 28 Aug 2026 18:26:26 +0200 Subject: [PATCH 01/42] Mechanical jspecify swap: fdb-relational-core api + util packages --- .../fdb-relational-core.gradle | 1 + .../api/EmbeddedRelationalArray.java | 23 +- .../api/EmbeddedRelationalDriver.java | 12 +- .../api/EmbeddedRelationalEngine.java | 3 +- .../api/EmbeddedRelationalStruct.java | 10 +- .../relational/api/ImmutableRowStruct.java | 3 +- .../relational/api/ProtobufDataBuilder.java | 7 +- .../foundationdb/relational/api/RowArray.java | 6 +- .../relational/api/StorageCluster.java | 8 +- .../relational/api/Transaction.java | 7 +- .../relational/api/TransactionManager.java | 4 +- .../api/catalog/CatalogValidator.java | 4 +- .../api/catalog/DatabaseSchema.java | 3 - .../catalog/NoOpSchemaTemplateCatalog.java | 18 +- .../api/catalog/RelationalDatabase.java | 6 +- .../api/catalog/SchemaExistsBehavior.java | 14 +- .../api/catalog/SchemaTemplateCatalog.java | 20 +- .../relational/api/catalog/StoreCatalog.java | 26 +- .../relational/api/catalog/package-info.java | 3 + .../api/ddl/CatalogQueryFactory.java | 5 +- .../relational/api/ddl/DdlQuery.java | 6 +- .../relational/api/ddl/DdlQueryFactory.java | 7 +- .../api/ddl/MetadataOperationsFactory.java | 25 +- .../relational/api/ddl/NoOpQueryFactory.java | 7 +- .../ddl/SaveSchemaTemplateConstantAction.java | 6 +- .../api/ddl/ThrowingQueryFactory.java | 9 +- .../relational/api/ddl/package-info.java | 3 + .../api/metrics/MetricCollector.java | 13 +- .../api/metrics/NoOpMetricRegistry.java | 3 - .../relational/api/metrics/package-info.java | 3 + .../relational/api/package-info.java | 3 + .../foundationdb/relational/util/Clocks.java | 3 +- .../relational/util/NullableArrayUtils.java | 6 +- .../relational/util/catalog/package-info.java | 3 + .../relational/util/package-info.java | 3 + .../api/catalog/CatalogValidatorTest.java | 4 - .../relational/api/catalog/package-info.java | 24 ++ .../api/ddl/AbstractQueryFactory.java | 7 +- .../api/ddl/DdlStatementParsingTest.java | 236 +++++++----------- .../relational/api/ddl/DdlTestUtil.java | 101 +++----- .../relational/api/ddl/IndexTest.java | 16 +- .../relational/api/ddl/SqlFunctionTest.java | 19 +- .../relational/api/ddl/package-info.java | 24 ++ .../relational/api/package-info.java | 24 ++ 44 files changed, 345 insertions(+), 393 deletions(-) create mode 100644 fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/catalog/package-info.java create mode 100644 fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/package-info.java create mode 100644 fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/package-info.java diff --git a/fdb-relational-core/fdb-relational-core.gradle b/fdb-relational-core/fdb-relational-core.gradle index 1daada44e7d..7a135d83328 100644 --- a/fdb-relational-core/fdb-relational-core.gradle +++ b/fdb-relational-core/fdb-relational-core.gradle @@ -36,6 +36,7 @@ dependencies { compileOnly(libs.autoService) annotationProcessor(libs.autoService) implementation(libs.jsr305) + compileOnly(libs.jspecify) implementation(libs.guava) implementation(libs.antlr) implementation(libs.log4j.core) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalArray.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalArray.java index fde820dd750..6db64f48646 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalArray.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalArray.java @@ -25,8 +25,8 @@ import com.apple.foundationdb.relational.api.metadata.DataType; import com.apple.foundationdb.relational.util.Assert; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; + import java.sql.SQLException; import java.util.ArrayList; import java.util.List; @@ -38,19 +38,19 @@ static RelationalArrayBuilder newBuilder() { return new Builder(); } - static RelationalArrayBuilder newBuilder(@Nonnull DataType elementType) { + static RelationalArrayBuilder newBuilder(DataType elementType) { return new Builder(elementType); } class Builder implements RelationalArrayBuilder { @Nullable private DataType elementType; - @Nonnull private final List elements = new ArrayList<>(); + private final List elements = new ArrayList<>(); private Builder() { } - private Builder(@Nonnull DataType elementType) { + private Builder(DataType elementType) { this.elementType = elementType; } @@ -63,7 +63,7 @@ public EmbeddedRelationalArray build() throws SQLException { } @Override - public Builder addAll(@Nonnull Object... values) throws SQLException { + public Builder addAll(Object... values) throws SQLException { for (var value : values) { if (value == null) { throw new RelationalException("Cannot add NULL to an array.", ErrorCode.DATATYPE_MISMATCH).toSqlException(); @@ -86,22 +86,22 @@ public Builder addLong(long value) throws SQLException { } @Override - public Builder addString(@Nonnull String value) throws SQLException { + public Builder addString(String value) throws SQLException { return addField(value, DataType.Primitives.STRING.type()); } @Override - public Builder addBytes(@Nonnull byte[] value) throws SQLException { + public Builder addBytes(byte[] value) throws SQLException { return addField(value, DataType.Primitives.BYTES.type()); } @Override - public Builder addUuid(@Nonnull UUID uuid) throws SQLException { + public Builder addUuid(UUID uuid) throws SQLException { return addField(uuid, DataType.Primitives.UUID.type()); } @Override - public Builder addObject(@Nonnull Object obj) throws SQLException { + public Builder addObject(Object obj) throws SQLException { if (obj instanceof RelationalStruct) { return addStruct((RelationalStruct) obj); } @@ -111,8 +111,7 @@ public Builder addObject(@Nonnull Object obj) throws SQLException { return addField(obj, DataType.getDataTypeFromObject(obj)); } - @Nonnull - private Builder addField(@Nonnull Object value, @Nonnull DataType type) throws SQLException { + private Builder addField(Object value, DataType type) throws SQLException { try { checkType(type); } catch (RelationalException ve) { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalDriver.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalDriver.java index 50b432a9fb8..f7fc1c6119c 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalDriver.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalDriver.java @@ -26,8 +26,8 @@ import com.apple.foundationdb.relational.api.exceptions.ErrorCode; import com.apple.foundationdb.relational.api.exceptions.RelationalException; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; + import java.net.URI; import java.sql.Connection; import java.sql.SQLException; @@ -53,15 +53,15 @@ public Connection connect(String url, Properties info) throws SQLException { } @Override - public RelationalConnection connect(@Nonnull URI url, - @Nonnull Options connectionOptions) throws SQLException { + public RelationalConnection connect(URI url, + Options connectionOptions) throws SQLException { return connect(url, null, connectionOptions); } @SuppressWarnings("PMD.CloseResource") // returns connection outliving auto-closeable object. Should consider refactoring - public RelationalConnection connect(@Nonnull URI url, + public RelationalConnection connect(URI url, @Nullable Transaction existingTransaction, - @Nonnull Options connectionOptions) throws SQLException { + Options connectionOptions) throws SQLException { final var urlString = url.toString(); if (!acceptsURL(urlString)) { return null; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalEngine.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalEngine.java index efddc4c34f2..f4e0b892918 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalEngine.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalEngine.java @@ -26,7 +26,6 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.MetricSet; -import javax.annotation.Nonnull; import java.util.Collection; import java.util.List; @@ -42,7 +41,7 @@ public class EmbeddedRelationalEngine { //TODO(bfines) eventually we need to move StoreCatalog into StorageCluster @SpotBugsSuppressWarnings(value = "CT_CONSTRUCTOR_THROW", justification = "May be refactored as embedded takes over transaction lifetime") public EmbeddedRelationalEngine(List fdbClusters, - @Nonnull MetricRegistry metricRegistry) { + MetricRegistry metricRegistry) { if (fdbClusters.isEmpty()) { throw new IllegalArgumentException("Must specify at least one FDB cluster to connect to"); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalStruct.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalStruct.java index b6f6ad2ad17..e52af0b3ba9 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalStruct.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalStruct.java @@ -24,8 +24,8 @@ import com.apple.foundationdb.relational.recordlayer.ArrayRow; import com.apple.foundationdb.relational.util.SpotBugsSuppressWarnings; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; + import java.sql.SQLException; import java.util.ArrayList; import java.util.List; @@ -101,13 +101,13 @@ public RelationalStructBuilder addObject(String fieldName, @Nullable Object obj) } @Override - public Builder addStruct(String fieldName, @Nonnull RelationalStruct struct) throws SQLException { + public Builder addStruct(String fieldName, RelationalStruct struct) throws SQLException { addField(fieldName, struct.getMetaData().getRelationalDataType(), struct); return this; } @Override - public Builder addArray(String fieldName, @Nonnull RelationalArray array) throws SQLException { + public Builder addArray(String fieldName, RelationalArray array) throws SQLException { addField(fieldName, array.getMetaData().asRelationalType(), array); return this; } @@ -117,7 +117,7 @@ public Builder addInt(String fieldName, int i) { return addField(fieldName, DataType.Primitives.INTEGER.type(), i); } - private Builder addField(@Nonnull String fieldName, @Nonnull DataType type, @Nullable Object o) { + private Builder addField(String fieldName, DataType type, @Nullable Object o) { fields.add(DataType.StructType.Field.from(fieldName, type, fields.size() + 1)); elements.add(o); return this; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ImmutableRowStruct.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ImmutableRowStruct.java index 9e2b28d4dfc..966b7212717 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ImmutableRowStruct.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ImmutableRowStruct.java @@ -25,7 +25,6 @@ import com.apple.foundationdb.relational.api.exceptions.InvalidColumnReferenceException; import com.apple.foundationdb.relational.api.exceptions.RelationalException; -import javax.annotation.Nonnull; import java.sql.SQLException; import java.util.Objects; @@ -37,7 +36,7 @@ public class ImmutableRowStruct extends RowStruct { private final Row theRow; - public ImmutableRowStruct(@Nonnull Row theRow, @Nonnull StructMetaData metaData) { + public ImmutableRowStruct(Row theRow, StructMetaData metaData) { super(metaData); this.theRow = theRow; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ProtobufDataBuilder.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ProtobufDataBuilder.java index 59646c91679..39cd15349d5 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ProtobufDataBuilder.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ProtobufDataBuilder.java @@ -30,7 +30,6 @@ import com.google.protobuf.DynamicMessage; import com.google.protobuf.Message; -import javax.annotation.Nonnull; import java.sql.SQLException; import java.util.Locale; import java.util.Set; @@ -99,7 +98,7 @@ public DynamicMessageBuilder setField(int fieldNumber, Object value) throws SQLE } } - private DynamicMessageBuilder setFieldInternal(@Nonnull final Descriptors.FieldDescriptor field, Object value) throws RelationalException { + private DynamicMessageBuilder setFieldInternal(final Descriptors.FieldDescriptor field, Object value) throws RelationalException { data.setField(field, coerceObject(value, field)); return this; } @@ -136,8 +135,7 @@ public DynamicMessageBuilder addRepeatedField(int fieldNumber, Object value) thr } } - @Nonnull - private DynamicMessageBuilder addRepeatedFieldInternal(@Nonnull final Descriptors.FieldDescriptor field, Object value) throws RelationalException { + private DynamicMessageBuilder addRepeatedFieldInternal(final Descriptors.FieldDescriptor field, Object value) throws RelationalException { data.addRepeatedField(field, coerceObject(value, field)); return this; } @@ -228,7 +226,6 @@ public Descriptors.Descriptor getDescriptor() { return typeDescriptor; } - @Nonnull @Override public DynamicMessageBuilder newBuilder() { return new ProtobufDataBuilder(typeDescriptor); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/RowArray.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/RowArray.java index c8f1487114c..7f51b84b888 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/RowArray.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/RowArray.java @@ -26,7 +26,6 @@ import com.apple.foundationdb.relational.recordlayer.IteratorResultSet; import com.google.common.base.Suppliers; -import javax.annotation.Nonnull; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; @@ -49,13 +48,13 @@ public class RowArray implements RelationalArray, EmbeddedRelationalArray { private final Supplier hashCodeSupplier; - public RowArray(@Nonnull List elements, @Nonnull ArrayMetaData arrayMetaData) { + public RowArray(List elements, ArrayMetaData arrayMetaData) { this.arrayMetaData = arrayMetaData; this.rows = Suppliers.memoize(() -> createIterableRows(elements)); this.hashCodeSupplier = Suppliers.memoize(this::calculateHashCode); } - private static List createIterableRows(@Nonnull List elements) { + private static List createIterableRows(List elements) { int i = 1; final List rows = new ArrayList<>(); for (var element : elements) { @@ -82,7 +81,6 @@ public int getBaseType() throws SQLException { return arrayMetaData.getElementType(); } - @Nonnull @Override public ArrayMetaData getMetaData() throws SQLException { return arrayMetaData; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/StorageCluster.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/StorageCluster.java index 68bf56a588d..9aeb8159035 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/StorageCluster.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/StorageCluster.java @@ -23,8 +23,8 @@ import com.apple.foundationdb.relational.api.catalog.RelationalDatabase; import com.apple.foundationdb.relational.api.exceptions.RelationalException; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; + import java.net.URI; /** @@ -48,8 +48,8 @@ public interface StorageCluster { * @throws RelationalException if something goes wrong. */ @Nullable - RelationalDatabase loadDatabase(@Nonnull URI url, - @Nonnull Options connOptions) throws RelationalException; + RelationalDatabase loadDatabase(URI url, + Options connOptions) throws RelationalException; /** * Get the transaction manager for this cluster. diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/Transaction.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/Transaction.java index 7ebade46820..d716b9676f2 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/Transaction.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/Transaction.java @@ -24,7 +24,6 @@ import com.apple.foundationdb.relational.api.exceptions.RelationalException; import com.apple.foundationdb.relational.api.metadata.SchemaTemplate; -import javax.annotation.Nonnull; import java.util.Optional; public interface Transaction extends AutoCloseable { @@ -42,7 +41,6 @@ public interface Transaction extends AutoCloseable { * @return An {@code Optional} containing the bound {@link SchemaTemplate}, or an empty {@link Optional} if no * template is bound. */ - @Nonnull Optional getBoundSchemaTemplateMaybe(); /** @@ -56,7 +54,7 @@ public interface Transaction extends AutoCloseable { * {@link SchemaTemplate} argument. * @param schemaTemplate The {@link SchemaTemplate} to bind. Must not be null. */ - void setBoundSchemaTemplate(@Nonnull SchemaTemplate schemaTemplate); + void setBoundSchemaTemplate(SchemaTemplate schemaTemplate); /** * Unsets the bound schema template, if one exists. @@ -77,8 +75,7 @@ public interface Transaction extends AutoCloseable { * @return this instance, as an instanceof Type T * @throws InternalErrorException if instance types are incompatible */ - @Nonnull - default T unwrap(@Nonnull Class type) throws InternalErrorException { + default T unwrap(Class type) throws InternalErrorException { Class myClass = this.getClass(); if (myClass.isAssignableFrom(type)) { return type.cast(this); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/TransactionManager.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/TransactionManager.java index 598cc07a4f0..f989cc5aa7f 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/TransactionManager.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/TransactionManager.java @@ -22,11 +22,9 @@ import com.apple.foundationdb.relational.api.exceptions.RelationalException; -import javax.annotation.Nonnull; - public interface TransactionManager { - Transaction createTransaction(@Nonnull Options connectionOptions) throws RelationalException; + Transaction createTransaction(Options connectionOptions) throws RelationalException; void abort(Transaction txn) throws RelationalException; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/CatalogValidator.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/CatalogValidator.java index 8d4da82ea9c..1c6f78fcfb5 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/CatalogValidator.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/CatalogValidator.java @@ -26,13 +26,11 @@ import com.apple.foundationdb.relational.api.exceptions.RelationalException; import com.apple.foundationdb.relational.api.metadata.Schema; -import javax.annotation.Nonnull; - @API(API.Status.EXPERIMENTAL) public final class CatalogValidator { // this seems superfluous, it can be replaced with proper checks in {@link Schema} constructor. - public static void validateSchema(@Nonnull Schema schema) throws RelationalException { + public static void validateSchema(Schema schema) throws RelationalException { // fields schema_name, schema_version, schema_template_name, database_id are required if (schema.getName() == null || schema.getName().isEmpty()) { throw new RelationalException("Field schema_name in Schema must be set!", ErrorCode.INVALID_PARAMETER); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/DatabaseSchema.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/DatabaseSchema.java index d4b74827844..86f9c780aa5 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/DatabaseSchema.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/DatabaseSchema.java @@ -23,12 +23,9 @@ import com.apple.foundationdb.relational.api.ConnectionScoped; import com.apple.foundationdb.relational.api.exceptions.RelationalException; -import javax.annotation.Nonnull; - @ConnectionScoped public interface DatabaseSchema extends AutoCloseable { - @Nonnull String getSchemaName(); @Override diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/NoOpSchemaTemplateCatalog.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/NoOpSchemaTemplateCatalog.java index 44f5108c4af..626477bdf2c 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/NoOpSchemaTemplateCatalog.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/NoOpSchemaTemplateCatalog.java @@ -32,8 +32,6 @@ import com.apple.foundationdb.relational.recordlayer.metadata.NoOpSchemaTemplate; import com.apple.foundationdb.relational.transactionbound.catalog.HollowSchemaTemplateCatalog; -import javax.annotation.Nonnull; - /** * Implementation of Schema template catalog that ignores CRUD operations on templates. This is essentially used * to instantiate a store catalog object that ends up not caring about the schema template in the Schema. @@ -50,27 +48,26 @@ public class NoOpSchemaTemplateCatalog extends HollowSchemaTemplateCatalog { @Override - public boolean doesSchemaTemplateExist(@Nonnull Transaction txn, @Nonnull String templateName, int version) { + public boolean doesSchemaTemplateExist(Transaction txn, String templateName, int version) { return true; } @Override - public boolean doesSchemaTemplateExist(@Nonnull Transaction txn, @Nonnull String templateName) { + public boolean doesSchemaTemplateExist(Transaction txn, String templateName) { return true; } @Override - public void createTemplate(@Nonnull Transaction txn, @Nonnull SchemaTemplate newTemplate) { + public void createTemplate(Transaction txn, SchemaTemplate newTemplate) { } - @Nonnull @Override - public SchemaTemplate loadSchemaTemplate(@Nonnull Transaction txn, @Nonnull String templateId, int version) { + public SchemaTemplate loadSchemaTemplate(Transaction txn, String templateId, int version) { return new NoOpSchemaTemplate(templateId, version); } @Override - public RelationalResultSet listTemplates(@Nonnull Transaction txn) { + public RelationalResultSet listTemplates(Transaction txn) { return new AbstractRecordLayerResultSet(null) { @Override protected boolean hasNext() { @@ -82,7 +79,6 @@ protected Row advanceRow() { return null; } - @Nonnull @Override public Continuation getContinuation() { return ContinuationImpl.BEGIN; @@ -100,11 +96,11 @@ public boolean isClosed() { } @Override - public void deleteTemplate(@Nonnull Transaction txn, @Nonnull String templateId, boolean throwIfDoesNotExist) { + public void deleteTemplate(Transaction txn, String templateId, boolean throwIfDoesNotExist) { } @Override - public void deleteTemplate(@Nonnull Transaction txn, @Nonnull String templateId, int version, boolean throwIfDoesNotExist) { + public void deleteTemplate(Transaction txn, String templateId, int version, boolean throwIfDoesNotExist) { } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/RelationalDatabase.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/RelationalDatabase.java index 7a049fc1344..8e4f5db67fb 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/RelationalDatabase.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/RelationalDatabase.java @@ -26,8 +26,7 @@ import com.apple.foundationdb.relational.api.ddl.MetadataOperationsFactory; import com.apple.foundationdb.relational.api.exceptions.RelationalException; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; /** * There can only be 1 Database object per Connection instance, and its lifecycle is managed by the connection @@ -45,9 +44,8 @@ public interface RelationalDatabase extends AutoCloseable { * @return a Schema for the specified id. * @throws RelationalException if something goes wrong during load */ - DatabaseSchema loadSchema(@Nonnull String schemaId) throws RelationalException; + DatabaseSchema loadSchema(String schemaId) throws RelationalException; - @Nonnull MetadataOperationsFactory getDdlFactory(); @Override diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/SchemaExistsBehavior.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/SchemaExistsBehavior.java index d95e77504a2..44a153bf2c5 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/SchemaExistsBehavior.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/SchemaExistsBehavior.java @@ -24,8 +24,6 @@ import com.apple.foundationdb.relational.api.exceptions.RelationalException; import com.apple.foundationdb.relational.api.metadata.Schema; -import javax.annotation.Nonnull; - /** * Governs what {@link StoreCatalog#saveSchema} does when a schema already exists at the * target {@code (databaseId, schemaName)} coordinate. @@ -45,7 +43,7 @@ public enum SchemaExistsBehavior { */ ERROR { @Override - public boolean shouldWrite(@Nonnull Schema newSchema, @Nonnull Schema existingSchema) throws RelationalException { + public boolean shouldWrite(Schema newSchema, Schema existingSchema) throws RelationalException { throw new RelationalException("Schema " + newSchema.getDatabaseName() + "/" + newSchema.getName() + " already exists.", ErrorCode.SCHEMA_ALREADY_EXISTS); } @@ -56,7 +54,7 @@ public boolean shouldWrite(@Nonnull Schema newSchema, @Nonnull Schema existingSc */ ERROR_IF_DIFFERENT { @Override - public boolean shouldWrite(@Nonnull Schema newSchema, @Nonnull Schema existingSchema) throws RelationalException { + public boolean shouldWrite(Schema newSchema, Schema existingSchema) throws RelationalException { if (areSchemasIdentical(newSchema, existingSchema)) { return false; } @@ -75,7 +73,7 @@ public boolean shouldWrite(@Nonnull Schema newSchema, @Nonnull Schema existingSc */ DO_NOTHING { @Override - public boolean shouldWrite(@Nonnull Schema newSchema, @Nonnull Schema existingSchema) { + public boolean shouldWrite(Schema newSchema, Schema existingSchema) { return false; } }, @@ -85,7 +83,7 @@ public boolean shouldWrite(@Nonnull Schema newSchema, @Nonnull Schema existingSc */ UPGRADE { @Override - public boolean shouldWrite(@Nonnull Schema newSchema, @Nonnull Schema existingSchema) throws RelationalException { + public boolean shouldWrite(Schema newSchema, Schema existingSchema) throws RelationalException { final String existingTemplateName = existingSchema.getSchemaTemplate().getName(); final String newTemplateName = newSchema.getSchemaTemplate().getName(); if (!existingTemplateName.equals(newTemplateName)) { @@ -122,13 +120,13 @@ public boolean shouldWrite(@Nonnull Schema newSchema, @Nonnull Schema existingSc * @throws RelationalException with {@link ErrorCode#SCHEMA_ALREADY_EXISTS} when this * behavior refuses the save */ - public abstract boolean shouldWrite(@Nonnull Schema newSchema, @Nonnull Schema existingSchema) throws RelationalException; + public abstract boolean shouldWrite(Schema newSchema, Schema existingSchema) throws RelationalException; /** * Return if the two provided schemas are identical. * @return {@code true} if and only if the two schemas are identical */ - private static boolean areSchemasIdentical(@Nonnull Schema a, @Nonnull Schema b) { + private static boolean areSchemasIdentical(Schema a, Schema b) { return a.getSchemaTemplate().getName().equals(b.getSchemaTemplate().getName()) && a.getSchemaTemplate().getVersion() == b.getSchemaTemplate().getVersion(); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/SchemaTemplateCatalog.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/SchemaTemplateCatalog.java index c912d95ea71..5dc02ba450d 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/SchemaTemplateCatalog.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/SchemaTemplateCatalog.java @@ -26,8 +26,6 @@ import com.apple.foundationdb.relational.api.exceptions.RelationalException; import com.apple.foundationdb.relational.api.metadata.SchemaTemplate; -import javax.annotation.Nonnull; - /** * A Catalog for holding Schema Templates. */ @@ -41,7 +39,7 @@ public interface SchemaTemplateCatalog { * @return whether the template exists. * @throws RelationalException if there is an exception with error code other than {@link ErrorCode#UNKNOWN_SCHEMA_TEMPLATE} */ - boolean doesSchemaTemplateExist(@Nonnull Transaction txn, @Nonnull String templateName) throws RelationalException; + boolean doesSchemaTemplateExist(Transaction txn, String templateName) throws RelationalException; /** * Checks if a specific version of the schema template exists. @@ -52,7 +50,7 @@ public interface SchemaTemplateCatalog { * @return whether the template exists. * @throws RelationalException if there is an exception with error code other than {@link ErrorCode#UNKNOWN_SCHEMA_TEMPLATE} */ - boolean doesSchemaTemplateExist(@Nonnull Transaction txn, @Nonnull String templateName, int version) throws RelationalException; + boolean doesSchemaTemplateExist(Transaction txn, String templateName, int version) throws RelationalException; /** * Loads the latest version of the specified schema template. @@ -63,8 +61,7 @@ public interface SchemaTemplateCatalog { * @throws RelationalException with {@link ErrorCode#UNKNOWN_SCHEMA_TEMPLATE} if the template * is not found, or with other error codes for additional failures */ - @Nonnull - SchemaTemplate loadSchemaTemplate(@Nonnull Transaction txn, @Nonnull String templateName) throws RelationalException; + SchemaTemplate loadSchemaTemplate(Transaction txn, String templateName) throws RelationalException; /** * Loads a specific version of the schema template. @@ -77,8 +74,7 @@ public interface SchemaTemplateCatalog { * or specified version is not found, or with other error codes * for additional failures */ - @Nonnull - SchemaTemplate loadSchemaTemplate(@Nonnull Transaction txn, @Nonnull String templateName, int version) throws RelationalException; + SchemaTemplate loadSchemaTemplate(Transaction txn, String templateName, int version) throws RelationalException; /** * Create the Schema template in the catalog associated with the templateId. @@ -87,9 +83,9 @@ public interface SchemaTemplateCatalog { * @param newTemplate the template to create * @throws RelationalException if something goes wrong, with an appropriate error code. */ - void createTemplate(@Nonnull Transaction txn, @Nonnull SchemaTemplate newTemplate) throws RelationalException; + void createTemplate(Transaction txn, SchemaTemplate newTemplate) throws RelationalException; - RelationalResultSet listTemplates(@Nonnull Transaction txn); + RelationalResultSet listTemplates(Transaction txn); /** * Deletes all versions of the schema template. @@ -98,7 +94,7 @@ public interface SchemaTemplateCatalog { * @param templateName the template to delete * @param throwIfDoesNotExist throw an exception if the template does not exist */ - void deleteTemplate(@Nonnull Transaction txn, @Nonnull String templateName, boolean throwIfDoesNotExist) throws RelationalException; + void deleteTemplate(Transaction txn, String templateName, boolean throwIfDoesNotExist) throws RelationalException; /** * Deletes a specific version of the schema template, if exists. @@ -109,5 +105,5 @@ public interface SchemaTemplateCatalog { * @param throwIfDoesNotExist throw an exception if the template does not exist * @throws RelationalException if something goes wrong, with an appropriate error code. */ - void deleteTemplate(@Nonnull Transaction txn, @Nonnull String templateName, int version, boolean throwIfDoesNotExist) throws RelationalException; + void deleteTemplate(Transaction txn, String templateName, int version, boolean throwIfDoesNotExist) throws RelationalException; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/StoreCatalog.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/StoreCatalog.java index 655be78e81d..c1dc49d8280 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/StoreCatalog.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/StoreCatalog.java @@ -26,7 +26,6 @@ import com.apple.foundationdb.relational.api.exceptions.RelationalException; import com.apple.foundationdb.relational.api.metadata.Schema; -import javax.annotation.Nonnull; import java.net.URI; /** @@ -52,8 +51,7 @@ public interface StoreCatalog { * InternalError if txn is incompatible type * TransactionInactive if txn is no longer active */ - @Nonnull - Schema loadSchema(@Nonnull Transaction txn, @Nonnull URI databaseId, @Nonnull String schemaName) throws RelationalException; + Schema loadSchema(Transaction txn, URI databaseId, String schemaName) throws RelationalException; /** * Save the given schema. @@ -65,8 +63,8 @@ public interface StoreCatalog { * values of this will affect how this save will conflict with other interactions to the schema. * @throws RelationalException if something goes wrong, with a specific ErrorCode saying what. */ - void saveSchema(@Nonnull Transaction txn, @Nonnull Schema dataToWrite, boolean createDatabaseIfNecessary, - @Nonnull SchemaExistsBehavior existsBehavior) throws RelationalException; + void saveSchema(Transaction txn, Schema dataToWrite, boolean createDatabaseIfNecessary, + SchemaExistsBehavior existsBehavior) throws RelationalException; /** * Updates schema to the latest template. @@ -78,9 +76,9 @@ void saveSchema(@Nonnull Transaction txn, @Nonnull Schema dataToWrite, boolean c * TransactionInactive if txn is no longer active * UNDEFINED_SCHEMA if schema not found */ - void repairSchema(@Nonnull Transaction txn, @Nonnull String databaseId, @Nonnull String schemaName) throws RelationalException; + void repairSchema(Transaction txn, String databaseId, String schemaName) throws RelationalException; - void createDatabase(@Nonnull Transaction txn, @Nonnull URI dbUri) throws RelationalException; + void createDatabase(Transaction txn, URI dbUri) throws RelationalException; /** * list databases in the entire Catalog. @@ -91,7 +89,7 @@ void saveSchema(@Nonnull Transaction txn, @Nonnull Schema dataToWrite, boolean c * @throws RelationalException InternalError if txn is incompatible type * TransactionInactive if txn is no longer active */ - RelationalResultSet listDatabases(@Nonnull Transaction txn, @Nonnull Continuation continuation) throws RelationalException; + RelationalResultSet listDatabases(Transaction txn, Continuation continuation) throws RelationalException; /** * list schemas in entire Catalog. @@ -102,7 +100,7 @@ void saveSchema(@Nonnull Transaction txn, @Nonnull Schema dataToWrite, boolean c * @throws RelationalException InternalError if txn is incompatible type * TransactionInactive if txn is no longer active */ - RelationalResultSet listSchemas(@Nonnull Transaction txn, @Nonnull Continuation continuation) throws RelationalException; + RelationalResultSet listSchemas(Transaction txn, Continuation continuation) throws RelationalException; /** * list schemas in a database. @@ -114,7 +112,7 @@ void saveSchema(@Nonnull Transaction txn, @Nonnull Schema dataToWrite, boolean c * @throws RelationalException InternalError if txn is incompatible type * TransactionInactive if txn is no longer active */ - RelationalResultSet listSchemas(@Nonnull Transaction txn, @Nonnull URI databaseId, @Nonnull Continuation continuation) throws RelationalException; + RelationalResultSet listSchemas(Transaction txn, URI databaseId, Continuation continuation) throws RelationalException; /** * Delete the schema from the Catalog. @@ -124,11 +122,11 @@ void saveSchema(@Nonnull Transaction txn, @Nonnull Schema dataToWrite, boolean c * @param schemaName the name of the schema to delete * @throws RelationalException if something goes wrong, with a specific ErrorCode saying what. */ - void deleteSchema(@Nonnull Transaction txn, @Nonnull URI dbUri, @Nonnull String schemaName) throws RelationalException; + void deleteSchema(Transaction txn, URI dbUri, String schemaName) throws RelationalException; - boolean doesDatabaseExist(@Nonnull Transaction txn, @Nonnull URI dbUrl) throws RelationalException; + boolean doesDatabaseExist(Transaction txn, URI dbUrl) throws RelationalException; - boolean doesSchemaExist(@Nonnull Transaction txn, @Nonnull URI dbUrl, @Nonnull String schemaName) throws RelationalException; + boolean doesSchemaExist(Transaction txn, URI dbUrl, String schemaName) throws RelationalException; /** * Delete the database from the Catalog. @@ -142,5 +140,5 @@ void saveSchema(@Nonnull Transaction txn, @Nonnull Schema dataToWrite, boolean c * @return {@code true} if the operation finishes, else returns {@code false} if the transaction expires * @throws RelationalException if something goes wrong, with a specific ErrorCode saying what. */ - boolean deleteDatabase(@Nonnull Transaction txn, @Nonnull URI dbUrl, boolean throwIfDoesNotExist) throws RelationalException; + boolean deleteDatabase(Transaction txn, URI dbUrl, boolean throwIfDoesNotExist) throws RelationalException; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/package-info.java index b6d301061e2..d059549734e 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/package-info.java @@ -21,4 +21,7 @@ /** * Interfaces and core API functions around implementing a Catalog instance. */ +@NullMarked package com.apple.foundationdb.relational.api.catalog; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/CatalogQueryFactory.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/CatalogQueryFactory.java index 0fdc812d130..9dfa9897e92 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/CatalogQueryFactory.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/CatalogQueryFactory.java @@ -29,7 +29,6 @@ import com.apple.foundationdb.relational.recordlayer.ContinuationImpl; import com.apple.foundationdb.relational.recordlayer.catalog.systables.SystemTableRegistry; -import javax.annotation.Nonnull; import java.net.URI; import java.util.List; import java.util.stream.Collectors; @@ -43,11 +42,10 @@ public CatalogQueryFactory(StoreCatalog catalog) { } @Override - public DdlQuery getListDatabasesQueryAction(@Nonnull URI prefixPath) { + public DdlQuery getListDatabasesQueryAction(URI prefixPath) { //TODO(bfines) make use of this prefix return new DdlQuery() { @Override - @Nonnull public Type getResultSetMetadata() { final List fieldNames = SystemTableRegistry.getSystemTable(SystemTableRegistry.DATABASE_TABLE_NAME).getType().getColumns().stream() .map(Metadata::getName) @@ -67,7 +65,6 @@ public DdlQuery getListSchemaTemplatesQueryAction() { final var columns = List.of("TEMPLATE_NAME"); return new DdlQuery() { @Override - @Nonnull public Type getResultSetMetadata() { return DdlQuery.constructTypeFrom(columns); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/DdlQuery.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/DdlQuery.java index 23673bd557d..4e578a04486 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/DdlQuery.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/DdlQuery.java @@ -25,7 +25,6 @@ import com.apple.foundationdb.relational.api.RelationalResultSet; import com.apple.foundationdb.relational.api.exceptions.RelationalException; -import javax.annotation.Nonnull; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -36,11 +35,9 @@ */ public interface DdlQuery extends DdlPreparedAction { - @Nonnull Type getResultSetMetadata(); - @Nonnull - static Type constructTypeFrom(@Nonnull final List columnNames) { + static Type constructTypeFrom(final List columnNames) { return Type.Record.fromFields(IntStream.range(0, columnNames.size()) .mapToObj(i -> Type.Record.Field.of( @@ -61,7 +58,6 @@ public RelationalResultSet executeAction(Transaction txn) throws RelationalExcep return null; } - @Nonnull @Override public Type getResultSetMetadata() { return new Type.Any(); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/DdlQueryFactory.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/DdlQueryFactory.java index b7fc01ebba1..165d46a9ac8 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/DdlQueryFactory.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/DdlQueryFactory.java @@ -20,7 +20,6 @@ package com.apple.foundationdb.relational.api.ddl; -import javax.annotation.Nonnull; import java.net.URI; /** @@ -31,11 +30,11 @@ */ public interface DdlQueryFactory { - DdlQuery getListDatabasesQueryAction(@Nonnull URI prefixPath); + DdlQuery getListDatabasesQueryAction(URI prefixPath); DdlQuery getListSchemaTemplatesQueryAction(); - DdlQuery getDescribeSchemaTemplateQueryAction(@Nonnull String schemaId); + DdlQuery getDescribeSchemaTemplateQueryAction(String schemaId); - DdlQuery getDescribeSchemaQueryAction(@Nonnull URI dbId, @Nonnull String schemaId); + DdlQuery getDescribeSchemaQueryAction(URI dbId, String schemaId); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/MetadataOperationsFactory.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/MetadataOperationsFactory.java index 5b598a3165e..a30cb4f0c89 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/MetadataOperationsFactory.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/MetadataOperationsFactory.java @@ -24,34 +24,25 @@ import com.apple.foundationdb.relational.api.metadata.SchemaTemplate; import com.apple.foundationdb.relational.recordlayer.metadata.RecordLayerInvokedRoutine; -import javax.annotation.Nonnull; import javax.annotation.concurrent.ThreadSafe; import java.net.URI; @ThreadSafe public interface MetadataOperationsFactory { - @Nonnull - ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, @Nonnull Options templateProperties); + ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, Options templateProperties); - @Nonnull - ConstantAction getDropSchemaTemplateConstantAction(@Nonnull String templateId, boolean throwIfDoesNotExist, @Nonnull Options options); + ConstantAction getDropSchemaTemplateConstantAction(String templateId, boolean throwIfDoesNotExist, Options options); - @Nonnull - ConstantAction getCreateDatabaseConstantAction(@Nonnull URI dbPath, @Nonnull Options constantActionOptions); + ConstantAction getCreateDatabaseConstantAction(URI dbPath, Options constantActionOptions); - @Nonnull - ConstantAction getCreateSchemaConstantAction(@Nonnull URI dbUri, @Nonnull String schemaName, @Nonnull String templateId, Options constantActionOptions); + ConstantAction getCreateSchemaConstantAction(URI dbUri, String schemaName, String templateId, Options constantActionOptions); - @Nonnull - ConstantAction getDropDatabaseConstantAction(@Nonnull URI dbUrl, boolean throwIfDoesNotExist, @Nonnull Options options); + ConstantAction getDropDatabaseConstantAction(URI dbUrl, boolean throwIfDoesNotExist, Options options); - @Nonnull - ConstantAction getDropSchemaConstantAction(@Nonnull URI dbPath, @Nonnull String schemaName, @Nonnull Options options); + ConstantAction getDropSchemaConstantAction(URI dbPath, String schemaName, Options options); - @Nonnull - ConstantAction getCreateTemporaryFunctionConstantAction(@Nonnull SchemaTemplate template, boolean throwIfExists, @Nonnull RecordLayerInvokedRoutine invokedRoutine); + ConstantAction getCreateTemporaryFunctionConstantAction(SchemaTemplate template, boolean throwIfExists, RecordLayerInvokedRoutine invokedRoutine); - @Nonnull - ConstantAction getDropTemporaryFunctionConstantAction(boolean throwIfNotExists, @Nonnull String temporaryFunctionName); + ConstantAction getDropTemporaryFunctionConstantAction(boolean throwIfNotExists, String temporaryFunctionName); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/NoOpQueryFactory.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/NoOpQueryFactory.java index 5878e0d3779..250bb96185a 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/NoOpQueryFactory.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/NoOpQueryFactory.java @@ -22,7 +22,6 @@ import com.apple.foundationdb.annotation.API; -import javax.annotation.Nonnull; import java.net.URI; @API(API.Status.EXPERIMENTAL) @@ -30,7 +29,7 @@ public class NoOpQueryFactory implements DdlQueryFactory { public static final DdlQueryFactory INSTANCE = new NoOpQueryFactory(); @Override - public DdlQuery getListDatabasesQueryAction(@Nonnull URI prefixPath) { + public DdlQuery getListDatabasesQueryAction(URI prefixPath) { return DdlQuery.NoOpDdlQuery.INSTANCE; } @@ -40,12 +39,12 @@ public DdlQuery getListSchemaTemplatesQueryAction() { } @Override - public DdlQuery getDescribeSchemaTemplateQueryAction(@Nonnull String schemaId) { + public DdlQuery getDescribeSchemaTemplateQueryAction(String schemaId) { return DdlQuery.NoOpDdlQuery.INSTANCE; } @Override - public DdlQuery getDescribeSchemaQueryAction(@Nonnull URI dbId, @Nonnull String schemaId) { + public DdlQuery getDescribeSchemaQueryAction(URI dbId, String schemaId) { return DdlQuery.NoOpDdlQuery.INSTANCE; } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/SaveSchemaTemplateConstantAction.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/SaveSchemaTemplateConstantAction.java index e8da0e017d6..b6d24f6cfc2 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/SaveSchemaTemplateConstantAction.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/SaveSchemaTemplateConstantAction.java @@ -27,15 +27,13 @@ import com.apple.foundationdb.relational.api.exceptions.RelationalException; import com.apple.foundationdb.relational.api.metadata.SchemaTemplate; -import javax.annotation.Nonnull; - @API(API.Status.EXPERIMENTAL) public class SaveSchemaTemplateConstantAction implements ConstantAction { private final SchemaTemplate template; private final SchemaTemplateCatalog catalog; - public SaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull SchemaTemplateCatalog catalog) { + public SaveSchemaTemplateConstantAction(SchemaTemplate template, + SchemaTemplateCatalog catalog) { this.template = template; this.catalog = catalog; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/ThrowingQueryFactory.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/ThrowingQueryFactory.java index 39e5a8efa7f..e82fdb4abdb 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/ThrowingQueryFactory.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/ThrowingQueryFactory.java @@ -24,7 +24,6 @@ import com.apple.foundationdb.relational.api.exceptions.ErrorCode; import com.apple.foundationdb.relational.api.exceptions.RelationalException; -import javax.annotation.Nonnull; import java.net.URI; /** @@ -40,14 +39,14 @@ public final class ThrowingQueryFactory implements DdlQueryFactory { private ThrowingQueryFactory() { } - private static RuntimeException reject(@Nonnull final String operation) { + private static RuntimeException reject(final String operation) { return new RelationalException( "DDL query '" + operation + "' is not allowed in this context", ErrorCode.UNSUPPORTED_OPERATION).toUncheckedWrappedException(); } @Override - public DdlQuery getListDatabasesQueryAction(@Nonnull URI prefixPath) { + public DdlQuery getListDatabasesQueryAction(URI prefixPath) { throw reject("SHOW DATABASES"); } @@ -57,12 +56,12 @@ public DdlQuery getListSchemaTemplatesQueryAction() { } @Override - public DdlQuery getDescribeSchemaTemplateQueryAction(@Nonnull String schemaId) { + public DdlQuery getDescribeSchemaTemplateQueryAction(String schemaId) { throw reject("DESCRIBE SCHEMA TEMPLATE"); } @Override - public DdlQuery getDescribeSchemaQueryAction(@Nonnull URI dbId, @Nonnull String schemaId) { + public DdlQuery getDescribeSchemaQueryAction(URI dbId, String schemaId) { throw reject("DESCRIBE SCHEMA"); } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/package-info.java index baa3c7a3a08..5bdadf18965 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/package-info.java @@ -21,4 +21,7 @@ /** * Objects relating to DDL operations within Relational. */ +@NullMarked package com.apple.foundationdb.relational.api.ddl; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/metrics/MetricCollector.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/metrics/MetricCollector.java index 9708c02cbda..e22aaeffdc4 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/metrics/MetricCollector.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/metrics/MetricCollector.java @@ -24,7 +24,6 @@ import com.apple.foundationdb.relational.api.exceptions.RelationalException; import com.apple.foundationdb.relational.util.Supplier; -import javax.annotation.Nonnull; import java.util.Locale; /** @@ -47,14 +46,14 @@ public interface MetricCollector { * @param count the count event to be modified * @param val the amount to increment by * */ - void increment(@Nonnull RelationalMetric.RelationalCount count, int val); + void increment(RelationalMetric.RelationalCount count, int val); /** * Increments the count event by 1. * * @param count the count event to be modified * */ - default void increment(@Nonnull RelationalMetric.RelationalCount count) { + default void increment(RelationalMetric.RelationalCount count) { increment(count, 1); } @@ -66,7 +65,7 @@ default void increment(@Nonnull RelationalMetric.RelationalCount count) { * @return the value returned by the supplier * @throws RelationalException that is passed on by the supplier * */ - T clock(@Nonnull RelationalMetric.RelationalEvent event, Supplier supplier) throws RelationalException; + T clock(RelationalMetric.RelationalEvent event, Supplier supplier) throws RelationalException; /** * Returns the aggregate time taken by all the occurrences of a particular event in the lifetime of collector. @@ -75,7 +74,7 @@ default void increment(@Nonnull RelationalMetric.RelationalCount count) { * @return the aggregate time in {@link java.util.concurrent.TimeUnit#MICROSECONDS}. * @throws RelationalException in case the requested event is not held in the collector. * */ - default double getAverageTimeMicrosForEvent(@Nonnull RelationalMetric.RelationalEvent event) throws RelationalException { + default double getAverageTimeMicrosForEvent(RelationalMetric.RelationalEvent event) throws RelationalException { throw new RelationalException(String.format(Locale.ROOT, "Requested event metric: %s is not in the collector", event.title()), ErrorCode.INTERNAL_ERROR); } @@ -86,7 +85,7 @@ default double getAverageTimeMicrosForEvent(@Nonnull RelationalMetric.Relational * @return the counter value * @throws RelationalException in case the requested count is not held in the collector. * */ - default long getCountsForCounter(@Nonnull RelationalMetric.RelationalCount count) throws RelationalException { + default long getCountsForCounter(RelationalMetric.RelationalCount count) throws RelationalException { throw new RelationalException(String.format(Locale.ROOT, "Requested count metric: %s is not in the collector", count.title()), ErrorCode.INTERNAL_ERROR); } @@ -96,7 +95,7 @@ default long getCountsForCounter(@Nonnull RelationalMetric.RelationalCount count * @param count the count event whose counter is to be checked. * @return {@code true} if counter is present, else false. */ - default boolean hasCounter(@Nonnull RelationalMetric.RelationalCount count) { + default boolean hasCounter(RelationalMetric.RelationalCount count) { return false; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/metrics/NoOpMetricRegistry.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/metrics/NoOpMetricRegistry.java index 6abc9e2311b..2709c6143fb 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/metrics/NoOpMetricRegistry.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/metrics/NoOpMetricRegistry.java @@ -24,8 +24,6 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.NoopMetricRegistry; -import javax.annotation.Nonnull; - /** * A utility for accessing a no-op {@link MetricRegistry}. *

@@ -36,7 +34,6 @@ @API(API.Status.EXPERIMENTAL) public final class NoOpMetricRegistry { - @Nonnull public static final MetricRegistry INSTANCE = new NoopMetricRegistry(); private NoOpMetricRegistry() { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/metrics/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/metrics/package-info.java index 555d9d33d7c..fe8f0cd5b4f 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/metrics/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/metrics/package-info.java @@ -21,4 +21,7 @@ /** * Keeper of Metrics stuff for Relational. */ +@NullMarked package com.apple.foundationdb.relational.api.metrics; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/package-info.java index 386e1c51019..1194926a43f 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/package-info.java @@ -24,4 +24,7 @@ * Code in this package (and it's subpackages) is the code which should be used by clients as they interact * with the Relational system. */ +@NullMarked package com.apple.foundationdb.relational.api; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/Clocks.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/Clocks.java index 84118ae77db..ad97a21ba4c 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/Clocks.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/Clocks.java @@ -22,7 +22,6 @@ import com.apple.foundationdb.annotation.API; -import javax.annotation.Nonnull; import java.util.concurrent.atomic.AtomicLong; /** @@ -55,7 +54,7 @@ public static Clock systemClock() { * @param ticker the underlying counter. * @return a clock which uses the underlying ticker to tell logical time. */ - public static Clock logicalClock(@Nonnull AtomicLong ticker) { + public static Clock logicalClock(AtomicLong ticker) { return ticker::get; } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/NullableArrayUtils.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/NullableArrayUtils.java index 65e85406c57..6b18b3aa133 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/NullableArrayUtils.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/NullableArrayUtils.java @@ -27,8 +27,6 @@ import com.google.protobuf.Descriptors; -import javax.annotation.Nonnull; - /** * A Utils class that holds logic related to nullable arrays. * Nullable Arrays are arrays that, if unset, will be NULL. @@ -59,7 +57,7 @@ public static boolean isWrappedArrayDescriptor(String fieldName, Descriptors.Des * Returns whether the given descriptor represents a wrapped ARRAY, that is, whether it contains a single repeated * field named {@code values}. */ - public static boolean isWrappedArrayDescriptor(@Nonnull final Descriptors.Descriptor descriptor) { + public static boolean isWrappedArrayDescriptor(final Descriptors.Descriptor descriptor) { return descriptor.getFields().size() == 1 && REPEATED_FIELD_NAME.equals(descriptor.getFields().get(0).getName()) && descriptor.findFieldByName(REPEATED_FIELD_NAME).isRepeated(); @@ -204,7 +202,7 @@ private static RecordKeyExpressionProto.KeyExpression wrapArrayInternal(RecordKe * } *} */ - private static RecordKeyExpressionProto.Nesting splitFieldIntoNestedWithValues(@Nonnull final RecordKeyExpressionProto.Field original) { + private static RecordKeyExpressionProto.Nesting splitFieldIntoNestedWithValues(final RecordKeyExpressionProto.Field original) { final var nestedArrayBuilder = RecordKeyExpressionProto.Field.newBuilder() .setFieldName(original.getFieldName()) .setFanType(RecordKeyExpressionProto.Field.FanType.SCALAR) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/catalog/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/catalog/package-info.java index f1997b20f64..ca51cd31e3e 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/catalog/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/catalog/package-info.java @@ -21,4 +21,7 @@ /** * Internal utils for the {@link com.apple.foundationdb.relational.api.catalog}. */ +@NullMarked package com.apple.foundationdb.relational.util.catalog; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/package-info.java index e50e6088b4c..5bafe438060 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/package-info.java @@ -21,4 +21,7 @@ /** * Utility methods to use in Relational implementation classes. */ +@NullMarked package com.apple.foundationdb.relational.util; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/catalog/CatalogValidatorTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/catalog/CatalogValidatorTest.java index 751c54d3510..eee5db7ff24 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/catalog/CatalogValidatorTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/catalog/CatalogValidatorTest.java @@ -31,7 +31,6 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import javax.annotation.Nonnull; import java.util.List; public class CatalogValidatorTest { @@ -83,7 +82,6 @@ void testValidateWithUnsetVersion() { Assertions.assertEquals("Field schema_version cannot be < 0!", exception.getMessage()); } - @Nonnull private RecordLayerSchema generateGoodSchema() { return RecordLayerSchemaTemplate .newBuilder() @@ -105,7 +103,6 @@ private RecordLayerSchema generateGoodSchema() { .generateSchema("test_db", "test_schema"); } - @Nonnull private RecordLayerSchema generateBadSchemaWithWrongVersion() { return RecordLayerSchemaTemplate .newBuilder() @@ -127,7 +124,6 @@ private RecordLayerSchema generateBadSchemaWithWrongVersion() { .generateSchema("test_db", "test_schema"); } - @Nonnull private RecordLayerSchema generateBadSchemaWithEmptySchemaTemplateName() { return RecordLayerSchemaTemplate .newBuilder() diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/catalog/package-info.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/catalog/package-info.java new file mode 100644 index 00000000000..a79d749b923 --- /dev/null +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/catalog/package-info.java @@ -0,0 +1,24 @@ +/* + * package-info.java + * + * This source file is part of the FoundationDB open source project + * + * Copyright 2021-2025 Apple Inc. and the FoundationDB project authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@NullMarked +package com.apple.foundationdb.relational.api.catalog; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/AbstractQueryFactory.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/AbstractQueryFactory.java index de2d587a797..6f8bb2a49b8 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/AbstractQueryFactory.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/AbstractQueryFactory.java @@ -20,12 +20,11 @@ package com.apple.foundationdb.relational.api.ddl; -import javax.annotation.Nonnull; import java.net.URI; public abstract class AbstractQueryFactory implements DdlQueryFactory { @Override - public DdlQuery getListDatabasesQueryAction(@Nonnull URI prefixPath) { + public DdlQuery getListDatabasesQueryAction(URI prefixPath) { return NoOpQueryFactory.INSTANCE.getListDatabasesQueryAction(prefixPath); } @@ -35,12 +34,12 @@ public DdlQuery getListSchemaTemplatesQueryAction() { } @Override - public DdlQuery getDescribeSchemaTemplateQueryAction(@Nonnull String schemaId) { + public DdlQuery getDescribeSchemaTemplateQueryAction(String schemaId) { return NoOpQueryFactory.INSTANCE.getDescribeSchemaTemplateQueryAction(schemaId); } @Override - public DdlQuery getDescribeSchemaQueryAction(@Nonnull URI dbId, @Nonnull String schemaId) { + public DdlQuery getDescribeSchemaQueryAction(URI dbId, String schemaId) { return NoOpQueryFactory.INSTANCE.getDescribeSchemaQueryAction(dbId, schemaId); } } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/DdlStatementParsingTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/DdlStatementParsingTest.java index 0b544bfdddd..7388cdb7227 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/DdlStatementParsingTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/DdlStatementParsingTest.java @@ -77,8 +77,8 @@ import org.junit.jupiter.params.provider.NullSource; import org.junit.jupiter.params.provider.ValueSource; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; + import java.net.URI; import java.sql.SQLException; import java.sql.Types; @@ -127,7 +127,6 @@ public static void setup() { "integer", "bigint", "double", "boolean", "string", "bytes", "vector(3, float)", "vector(4, double)", "vector(5, half)" }; - @Nonnull static Stream> columnTypePermutations() { int numColumns = 2; final List items = List.of(validPrimitiveDataTypes); @@ -135,13 +134,12 @@ static Stream> columnTypePermutations() { return PermutationIterator.generatePermutations(items, numColumns).stream(); } - @Nonnull static Stream indexSyntaxAndColumnTypes() { return columnTypePermutations().flatMap(permutation -> Arrays.stream(DdlTestUtil.IndexSyntax.values()) .map(syntax -> Arguments.of(syntax, permutation))); } - void shouldFailWith(@Nonnull final String query, @Nullable final ErrorCode errorCode) throws Exception { + void shouldFailWith(final String query, @Nullable final ErrorCode errorCode) throws Exception { connection.setAutoCommit(false); (connection.getUnderlyingEmbeddedConnection()).createNewTransaction(); final RelationalException ve = Assertions.assertThrows(RelationalException.class, () -> @@ -152,8 +150,8 @@ void shouldFailWith(@Nonnull final String query, @Nullable final ErrorCode error connection.setAutoCommit(true); } - void shouldFailWithInjectedFactory(@Nonnull final String query, @Nullable final ErrorCode errorCode, - @Nonnull final MetadataOperationsFactory metadataOperationsFactory) throws Exception { + void shouldFailWithInjectedFactory(final String query, @Nullable final ErrorCode errorCode, + final MetadataOperationsFactory metadataOperationsFactory) throws Exception { connection.setAutoCommit(false); (connection.getUnderlyingEmbeddedConnection()).createNewTransaction(); final RelationalException ve = Assertions.assertThrows(RelationalException.class, () -> @@ -164,8 +162,8 @@ void shouldFailWithInjectedFactory(@Nonnull final String query, @Nullable final connection.setAutoCommit(true); } - void shouldWorkWithInjectedFactory(@Nonnull final String query, - @Nonnull final MetadataOperationsFactory metadataOperationsFactory) throws Exception { + void shouldWorkWithInjectedFactory(final String query, + final MetadataOperationsFactory metadataOperationsFactory) throws Exception { connection.setAutoCommit(false); (connection.getUnderlyingEmbeddedConnection()).createNewTransaction(); final var transaction = connection.getUnderlyingEmbeddedConnection().getTransaction(); @@ -179,8 +177,8 @@ void shouldWorkWithInjectedFactory(@Nonnull final String query, connection.setAutoCommit(true); } - void shouldFailWithInjectedQueryFactory(@Nonnull final String query, @Nullable ErrorCode errorCode, - @Nonnull final DdlQueryFactory queryFactory) throws Exception { + void shouldFailWithInjectedQueryFactory(final String query, @Nullable ErrorCode errorCode, + final DdlQueryFactory queryFactory) throws Exception { connection.setAutoCommit(false); (connection.getUnderlyingEmbeddedConnection()).createNewTransaction(); final RelationalException ve = Assertions.assertThrows(RelationalException.class, () -> @@ -191,7 +189,7 @@ void shouldFailWithInjectedQueryFactory(@Nonnull final String query, @Nullable E Assertions.assertEquals(errorCode, ve.getErrorCode()); } - void shouldWorkWithInjectedQueryFactory(@Nonnull final String query, @Nonnull DdlQueryFactory queryFactory) throws Exception { + void shouldWorkWithInjectedQueryFactory(final String query, DdlQueryFactory queryFactory) throws Exception { connection.setAutoCommit(false); (connection.getUnderlyingEmbeddedConnection()).createNewTransaction(); final var transaction = connection.getUnderlyingEmbeddedConnection().getTransaction(); @@ -204,8 +202,7 @@ void shouldWorkWithInjectedQueryFactory(@Nonnull final String query, @Nonnull Dd connection.setAutoCommit(true); } - @Nonnull - private static DescriptorProtos.FileDescriptorProto getProtoDescriptor(@Nonnull final SchemaTemplate schemaTemplate) { + private static DescriptorProtos.FileDescriptorProto getProtoDescriptor(final SchemaTemplate schemaTemplate) { Assertions.assertInstanceOf(RecordLayerSchemaTemplate.class, schemaTemplate); final var asRecordLayerSchemaTemplate = (RecordLayerSchemaTemplate)schemaTemplate; return asRecordLayerSchemaTemplate.toRecordMetadata().toProto().getRecords(); @@ -259,9 +256,8 @@ void basicEnumParsedCorrectly() throws Exception { "CREATE TABLE my_table (id bigint, enum_field my_enum, PRIMARY KEY(id))"; shouldWorkWithInjectedFactory(stmt, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, Options templateProperties) { Assertions.assertInstanceOf(RecordLayerSchemaTemplate.class, template); Assertions.assertEquals(1, ((RecordLayerSchemaTemplate)template).getTables().size(), "should have only 1 table"); DescriptorProtos.FileDescriptorProto fileDescriptorProto = getProtoDescriptor(template); @@ -296,14 +292,13 @@ private static Stream typesMap() { @ParameterizedTest @MethodSource("typesMap") - void columnTypeWithNull(int sqlType, @Nonnull String sqlTypeName) throws Exception { + void columnTypeWithNull(int sqlType, String sqlTypeName) throws Exception { final String stmt = "CREATE SCHEMA TEMPLATE test_template " + "CREATE TYPE AS STRUCT baz (a bigint, b bigint) " + "CREATE TABLE bar (id bigint, foo_field " + sqlTypeName + " null, PRIMARY KEY(id))"; shouldWorkWithInjectedFactory(stmt, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull final SchemaTemplate template, @Nonnull final Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(final SchemaTemplate template, final Options templateProperties) { checkColumnNullability(template, sqlType, true); return txn -> { }; @@ -313,15 +308,14 @@ public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull final SchemaT @ParameterizedTest @MethodSource("typesMap") - void columnTypeWithNotNull(int sqlType, @Nonnull String sqlTypeName) throws Exception { + void columnTypeWithNotNull(int sqlType, String sqlTypeName) throws Exception { final String stmt = "CREATE SCHEMA TEMPLATE test_template " + "CREATE TYPE AS STRUCT baz (a bigint, b bigint) " + "CREATE TABLE bar (id bigint, foo_field " + sqlTypeName + " not null, PRIMARY KEY(id))"; if (sqlType == Types.ARRAY) { shouldWorkWithInjectedFactory(stmt, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull final SchemaTemplate template, @Nonnull final Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(final SchemaTemplate template, final Options templateProperties) { checkColumnNullability(template, sqlType, false); return txn -> { }; @@ -350,10 +344,9 @@ void failsToParseEmptyTemplateStatements() throws Exception { final String stmt = "CREATE SCHEMA TEMPLATE test_template "; boolean[] visited = new boolean[] {false}; shouldFailWithInjectedFactory(stmt, ErrorCode.SYNTAX_ERROR, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, + Options templateProperties) { Assertions.assertInstanceOf(RecordLayerSchemaTemplate.class, template); Assertions.assertEquals(0, ((RecordLayerSchemaTemplate)template).getTables().size(), "Tables defined!"); visited[0] = true; @@ -369,10 +362,9 @@ void createTypeWithPrimaryKeyFails() throws Exception { final String stmt = "CREATE SCHEMA TEMPLATE test_template " + "CREATE TYPE AS STRUCT t (a bigint, b string, PRIMARY KEY(b))"; shouldFailWithInjectedFactory(stmt, ErrorCode.SYNTAX_ERROR, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, + Options templateProperties) { Assertions.fail("Should fail during parsing!"); return txn -> { }; @@ -402,9 +394,8 @@ void translateNames() throws Exception { "CREATE FUNCTION \"a.b$c__macro_function\"(in \"__in__4a.b$c__table\" TYPE \"__4a.b$c__table\") RETURNS string AS \"__in__4a.b$c__table\".\"__h__s\".\"_b.x\" "; shouldWorkWithInjectedFactory(stmt, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull final SchemaTemplate template, @Nonnull final Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(final SchemaTemplate template, final Options templateProperties) { try { // Assert all the user-visible names look like the user identifiers in the schema @@ -507,7 +498,6 @@ public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull final SchemaT }); } - @Nonnull private static Stream invalidVectorTypes() { return Stream.of( // Zero dimensions @@ -559,10 +549,9 @@ void createSchemaTemplateWithOutOfOrderDefinitionsWork(List columns) thr "CREATE TYPE AS STRUCT FOO " + makeColumnDefinition(columns, false); shouldWorkWithInjectedFactory(templateStatement, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, + Options templateProperties) { Assertions.assertInstanceOf(RecordLayerSchemaTemplate.class, template); Assertions.assertEquals(1, ((RecordLayerSchemaTemplate)template).getTables().size(), "Incorrect number of tables"); return txn -> { @@ -579,10 +568,9 @@ void createSchemaTemplates(List columns) throws Exception { " CREATE TYPE AS STRUCT foo " + makeColumnDefinition(columns, false) + " CREATE TABLE bar (col0 bigint, col1 foo, PRIMARY KEY(col0))"; shouldWorkWithInjectedFactory(columnStatement, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, + Options templateProperties) { Assertions.assertEquals("test_template", template.getName(), "incorrect template name!"); DdlTestUtil.ParsedSchema schema = new DdlTestUtil.ParsedSchema(getProtoDescriptor(template)); Assertions.assertEquals(1, schema.getTables().size(), "Incorrect number of tables"); @@ -606,10 +594,9 @@ void createSchemaTemplatesWithRowVersions(List columns) throws Exception " CREATE TABLE bar (col0 bigint, col1 foo, PRIMARY KEY(col0)) " + " WITH OPTIONS(store_row_versions=true) "; shouldWorkWithInjectedFactory(columnStatement, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, + Options templateProperties) { Assertions.assertEquals("test_template", template.getName(), "incorrect template name!"); DdlTestUtil.ParsedSchema schema = new DdlTestUtil.ParsedSchema(getProtoDescriptor(template)); Assertions.assertEquals(1, schema.getTables().size(), "Incorrect number of tables"); @@ -635,10 +622,9 @@ void createSchemaTemplateTableWithOnlyRecordType(List columns) throws Ex "CREATE TABLE foo " + baseTableDef; shouldWorkWithInjectedFactory(columnStatement, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, + Options templateProperties) { Assertions.assertEquals("test_template", template.getName(), "incorrect template name!"); DdlTestUtil.ParsedSchema schema = new DdlTestUtil.ParsedSchema(getProtoDescriptor(template)); Assertions.assertEquals(1, schema.getTables().size(), "Incorrect number of tables"); @@ -664,10 +650,9 @@ void createSchemaTemplateWithDuplicateIndexesFails(DdlTestUtil.IndexSyntax index DdlTestUtil.generateIndexDdlStatement(indexSyntax, "foo_idx", List.of(new IndexedColumn("col1")), List.of(), "foo"); //duplicate with the same name on same table should fail shouldFailWithInjectedFactory(columnStatement, ErrorCode.INDEX_ALREADY_EXISTS, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, + Options templateProperties) { Assertions.fail("Should not call this!"); return txn -> { }; @@ -685,10 +670,9 @@ void createSchemaTemplateWithIndex(DdlTestUtil.IndexSyntax indexSyntax, List { @@ -820,9 +801,8 @@ void createSchemaTemplateWithNoTypesFails() throws Exception { final String command = "CREATE SCHEMA TEMPLATE no_types ;"; // parser rules design doesn't permit this case. shouldFailWithInjectedFactory(command, ErrorCode.SYNTAX_ERROR, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, Options templateProperties) { Assertions.fail("Should fail with a parser error"); return super.getSaveSchemaTemplateConstantAction(template, templateProperties); } @@ -835,10 +815,9 @@ void createTable(List columns) throws Exception { final String columnStatement = "CREATE SCHEMA TEMPLATE test_template CREATE TABLE foo " + makeColumnDefinition(columns, true); shouldWorkWithInjectedFactory(columnStatement, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, + Options templateProperties) { Assertions.assertEquals("test_template", template.getName(), "incorrect template name!"); DdlTestUtil.ParsedSchema schema = new DdlTestUtil.ParsedSchema(getProtoDescriptor(template)); Assertions.assertEquals(1, schema.getTables().size(), "Incorrect number of tables"); @@ -867,10 +846,9 @@ void createTableAndType(List columns) throws Exception { tableDef; shouldWorkWithInjectedFactory(templateStatement, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, + Options templateProperties) { Assertions.assertEquals("test_template", template.getName(), "incorrect template name!"); DdlTestUtil.ParsedSchema schema = new DdlTestUtil.ParsedSchema(getProtoDescriptor(template)); Assertions.assertEquals(1, schema.getTables().size(), "Incorrect number of tables"); @@ -892,9 +870,8 @@ void createDatabase() throws Exception { final String command = "CREATE DATABASE /db_path"; shouldWorkWithInjectedFactory(command, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getCreateDatabaseConstantAction(@Nonnull URI dbPath, @Nonnull Options constantActionOptions) { + public ConstantAction getCreateDatabaseConstantAction(URI dbPath, Options constantActionOptions) { Assertions.assertEquals(URI.create("/db_path"), dbPath, "Incorrect database path!"); return NoOpMetadataOperationsFactory.INSTANCE.getCreateDatabaseConstantAction(dbPath, constantActionOptions); } @@ -906,9 +883,8 @@ void createDatabaseWithInvalidPathFails() throws Exception { final String command = "CREATE DATABASE not_a_path"; shouldFailWithInjectedFactory(command, ErrorCode.INVALID_PATH, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getCreateDatabaseConstantAction(@Nonnull URI dbPath, @Nonnull Options constantActionOptions) { + public ConstantAction getCreateDatabaseConstantAction(URI dbPath, Options constantActionOptions) { Assertions.fail("We should not reach this point! We should throw a RelationalException instead"); return NoOpMetadataOperationsFactory.INSTANCE.getCreateDatabaseConstantAction(dbPath, constantActionOptions); } @@ -920,9 +896,8 @@ void dropDatabase() throws Exception { final String command = "DROP DATABASE \"/db_path\""; shouldWorkWithInjectedFactory(command, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getDropDatabaseConstantAction(@Nonnull URI dbUrl, boolean throwIfDoesNotExist, @Nonnull Options options) { + public ConstantAction getDropDatabaseConstantAction(URI dbUrl, boolean throwIfDoesNotExist, Options options) { Assertions.assertEquals(URI.create("/db_path"), dbUrl, "Incorrect database path!"); return NoOpMetadataOperationsFactory.INSTANCE.getDropDatabaseConstantAction(dbUrl, throwIfDoesNotExist, options); } @@ -934,9 +909,8 @@ void dropDatabaseWithInvalidPathFails() throws Exception { final String command = "DROP DATABASE not_a_path"; shouldFailWithInjectedFactory(command, ErrorCode.INVALID_PATH, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getDropDatabaseConstantAction(@Nonnull URI dbUrl, boolean throwIfDoesNotExist, @Nonnull Options options) { + public ConstantAction getDropDatabaseConstantAction(URI dbUrl, boolean throwIfDoesNotExist, Options options) { Assertions.fail("We should not reach this point! We should throw a RelationalException instead"); return NoOpMetadataOperationsFactory.INSTANCE.getCreateDatabaseConstantAction(dbUrl, options); } @@ -950,7 +924,7 @@ void listDatabasesWithoutPrefixParsesCorrectly() throws Exception { boolean[] called = new boolean[] {false}; shouldWorkWithInjectedQueryFactory(command, new AbstractQueryFactory() { @Override - public DdlQuery getListDatabasesQueryAction(@Nonnull URI prefixPath) { + public DdlQuery getListDatabasesQueryAction(URI prefixPath) { called[0] = true; Assertions.assertNotNull(prefixPath, "Null URI passed!"); Assertions.assertEquals(URI.create("/" + DdlStatementParsingTest.class.getSimpleName()), prefixPath, "incorrect root path specified!"); @@ -969,7 +943,7 @@ void listDatabasesWithPrefixParsesCorrectly() throws Exception { shouldWorkWithInjectedQueryFactory(command, new AbstractQueryFactory() { @Override - public DdlQuery getListDatabasesQueryAction(@Nonnull URI prefixPath) { + public DdlQuery getListDatabasesQueryAction(URI prefixPath) { called[0] = true; Assertions.assertNotNull(prefixPath, "Null URI passed!"); Assertions.assertEquals(URI.create("/PREFIX"), prefixPath, "incorrect prefixed path specified!"); @@ -987,7 +961,7 @@ void listSchemaTemplatesParsesProperly() throws Exception { boolean[] called = new boolean[] {false}; shouldWorkWithInjectedQueryFactory(command, new AbstractQueryFactory() { @Override - public DdlQuery getListDatabasesQueryAction(@Nonnull URI prefixPath) { + public DdlQuery getListDatabasesQueryAction(URI prefixPath) { Assertions.fail("Incorrectly called listSchemas!"); return DdlQuery.NoOpDdlQuery.INSTANCE; } @@ -1021,7 +995,7 @@ void describeSchemaTemplate() throws Exception { boolean[] called = new boolean[] {false}; shouldWorkWithInjectedQueryFactory("DESCRIBE SCHEMA TEMPLATE " + templateName, new AbstractQueryFactory() { @Override - public DdlQuery getDescribeSchemaTemplateQueryAction(@Nonnull String schemaId) { + public DdlQuery getDescribeSchemaTemplateQueryAction(String schemaId) { called[0] = true; Assertions.assertNotNull(schemaId, "Passed a null schema id!"); Assertions.assertEquals(templateName, schemaId, "Incorrect template name!"); @@ -1037,7 +1011,7 @@ void describeSchemaTemplateFailsWithNoTemplateId() throws Exception { shouldFailWithInjectedQueryFactory(query, ErrorCode.SYNTAX_ERROR, new AbstractQueryFactory() { @Override - public DdlQuery getDescribeSchemaTemplateQueryAction(@Nonnull String schemaId) { + public DdlQuery getDescribeSchemaTemplateQueryAction(String schemaId) { Assertions.fail("Should not call the query!"); return DdlQuery.NoOpDdlQuery.INSTANCE; } @@ -1050,7 +1024,7 @@ void describeFailsWithNoIdentifier() throws Exception { shouldFailWithInjectedQueryFactory(query, ErrorCode.SYNTAX_ERROR, new AbstractQueryFactory() { @Override - public DdlQuery getDescribeSchemaTemplateQueryAction(@Nonnull String schemaId) { + public DdlQuery getDescribeSchemaTemplateQueryAction(String schemaId) { Assertions.fail("Should not call the query!"); return DdlQuery.NoOpDdlQuery.INSTANCE; } @@ -1064,7 +1038,7 @@ void describeSchemaSucceedsWithoutDatabase() throws Exception { // because parse boolean[] called = new boolean[] {false}; shouldWorkWithInjectedQueryFactory("DESCRIBE SCHEMA " + templateName, new AbstractQueryFactory() { @Override - public DdlQuery getDescribeSchemaQueryAction(@Nonnull URI dbUri, @Nonnull String schemaId) { + public DdlQuery getDescribeSchemaQueryAction(URI dbUri, String schemaId) { called[0] = true; Assertions.assertNotNull(schemaId, "Passed a null schema id!"); Assertions.assertNotNull(dbUri, "Passed a null db id!"); @@ -1082,7 +1056,7 @@ void describeSchemaPathSucceeds() throws Exception { boolean[] called = new boolean[] {false}; shouldWorkWithInjectedQueryFactory("DESCRIBE SCHEMA " + "/test_db/" + templateName, new AbstractQueryFactory() { @Override - public DdlQuery getDescribeSchemaQueryAction(@Nonnull URI dbUri, @Nonnull String schemaId) { + public DdlQuery getDescribeSchemaQueryAction(URI dbUri, String schemaId) { called[0] = true; Assertions.assertNotNull(schemaId, "Passed a null schema id!"); Assertions.assertNotNull(dbUri, "Passed a null db id!"); @@ -1100,7 +1074,7 @@ void describeSchemaWithSetDatabaseSucceeds() throws Exception { boolean[] called = new boolean[] {false}; shouldWorkWithInjectedQueryFactory("DESCRIBE SCHEMA " + templateName, new AbstractQueryFactory() { @Override - public DdlQuery getDescribeSchemaQueryAction(@Nonnull URI dbUri, @Nonnull String schemaId) { + public DdlQuery getDescribeSchemaQueryAction(URI dbUri, String schemaId) { called[0] = true; Assertions.assertNotNull(schemaId, "Passed a null schema id!"); Assertions.assertNotNull(dbUri, "Passed a null db id!"); @@ -1117,11 +1091,10 @@ void createSchemaWithPath() throws Exception { boolean[] called = new boolean[] {false}; shouldWorkWithInjectedFactory("CREATE SCHEMA /test_db/" + templateName + " WITH TEMPLATE " + templateName, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getCreateSchemaConstantAction(@Nonnull URI dbUri, - @Nonnull String schemaName, - @Nonnull String templateId, + public ConstantAction getCreateSchemaConstantAction(URI dbUri, + String schemaName, + String templateId, Options constantActionOptions) { called[0] = true; Assertions.assertNotNull(dbUri, "No database URI specified"); @@ -1141,10 +1114,9 @@ public void bitmapIndexCreationShouldWork() throws Exception { "CREATE INDEX all_seen_uids_bitmap AS SELECT bitmap_construct_agg(bitmap_bit_position(uid)) FROM msgstate GROUP BY mboxRef, isSeen, bitmap_bucket_offset(uid)"; shouldWorkWithInjectedFactory(schemaStatement, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, + Options templateProperties) { return txn -> { }; } @@ -1160,10 +1132,9 @@ void createViewWorks() throws Exception { "CREATE VIEW v AS SELECT * FROM bar"; shouldWorkWithInjectedFactory(schemaStatement, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, + Options templateProperties) { final var viewMaybe = Assertions.assertDoesNotThrow(() -> template.findViewByName("v")); assertThat(viewMaybe).isPresent(); assertThat(Assert.optionalUnchecked(viewMaybe).getDescription()).isEqualTo("SELECT * FROM bar"); @@ -1183,10 +1154,9 @@ void createNestedViewWorks() throws Exception { "CREATE VIEW v2 AS SELECT * FROM v1"; shouldWorkWithInjectedFactory(schemaStatement, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, + Options templateProperties) { final var view1Maybe = Assertions.assertDoesNotThrow(() -> template.findViewByName("v1")); assertThat(view1Maybe).isPresent(); assertThat(Assert.optionalUnchecked(view1Maybe).getDescription()).isEqualTo("SELECT * FROM bar"); @@ -1221,7 +1191,7 @@ void createViewWithCollidingNameDoesNotWorkCase1() throws Exception { shouldFailWithInjectedQueryFactory(schemaStatement, ErrorCode.INVALID_SCHEMA_TEMPLATE, new AbstractQueryFactory() { @Override - public DdlQuery getDescribeSchemaTemplateQueryAction(@Nonnull String schemaId) { + public DdlQuery getDescribeSchemaTemplateQueryAction(String schemaId) { Assertions.fail("Should not call the query!"); return DdlQuery.NoOpDdlQuery.INSTANCE; } @@ -1239,7 +1209,7 @@ void createViewWithCollidingNameDoesNotWorkCase2() throws Exception { shouldFailWithInjectedQueryFactory(schemaStatement, ErrorCode.INVALID_SCHEMA_TEMPLATE, new AbstractQueryFactory() { @Override - public DdlQuery getDescribeSchemaTemplateQueryAction(@Nonnull String schemaId) { + public DdlQuery getDescribeSchemaTemplateQueryAction(String schemaId) { Assertions.fail("Should not call the query!"); return DdlQuery.NoOpDdlQuery.INSTANCE; } @@ -1256,7 +1226,7 @@ void createInvalidViewDefinitionDoesNotWork() throws Exception { shouldFailWithInjectedQueryFactory(schemaStatement, ErrorCode.SYNTAX_ERROR, new AbstractQueryFactory() { @Override - public DdlQuery getDescribeSchemaTemplateQueryAction(@Nonnull String schemaId) { + public DdlQuery getDescribeSchemaTemplateQueryAction(String schemaId) { Assertions.fail("Should not call the query!"); return DdlQuery.NoOpDdlQuery.INSTANCE; } @@ -1283,10 +1253,9 @@ void createViewWithCteWorks() throws Exception { "CREATE TABLE bar (id bigint, baz_field baz, foo_field foo, PRIMARY KEY(id)) "; shouldWorkWithInjectedFactory(schemaStatement, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, + Options templateProperties) { final var viewMaybe = Assertions.assertDoesNotThrow(() -> template.findViewByName("v")); assertThat(viewMaybe).isPresent(); assertThat(Assert.optionalUnchecked(viewMaybe).getDescription()).isEqualTo("WITH C1 AS (SELECT foo_field, id, baz_field FROM bar where id > 20) SELECT * FROM C1"); @@ -1305,10 +1274,9 @@ void createViewWithNestedCteWorks() throws Exception { "CREATE TABLE bar (id bigint, baz_field baz, foo_field foo, PRIMARY KEY(id)) "; shouldWorkWithInjectedFactory(schemaStatement, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, + Options templateProperties) { final var viewMaybe = Assertions.assertDoesNotThrow(() -> template.findViewByName("v")); assertThat(viewMaybe).isPresent(); assertThat(Assert.optionalUnchecked(viewMaybe).getDescription()).isEqualTo("WITH C1 AS (WITH C2 AS (SELECT foo_field, id, baz_field FROM bar where id > 20) SELECT * FROM C2) SELECT * FROM C1"); @@ -1328,10 +1296,9 @@ void createViewWithFunctionAndCteComplexNestingWorks() throws Exception { "CREATE VIEW v AS WITH C1 AS (WITH C2 AS (SELECT foo_field, id, baz_field FROM F1(20)) SELECT * FROM C2) SELECT * FROM C1 "; shouldWorkWithInjectedFactory(schemaStatement, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, + Options templateProperties) { final var viewMaybe = Assertions.assertDoesNotThrow(() -> template.findViewByName("v")); assertThat(viewMaybe).isPresent(); assertThat(Assert.optionalUnchecked(viewMaybe).getDescription()).isEqualTo("WITH C1 AS (WITH C2 AS (SELECT foo_field, id, baz_field FROM F1(20)) SELECT * FROM C2) SELECT * FROM C1"); @@ -1354,7 +1321,7 @@ void createViewWithFunctionAndCteReferencingAnotherViewDoesNotWork() throws Exce shouldFailWithInjectedQueryFactory(schemaStatement, ErrorCode.UNDEFINED_TABLE, new AbstractQueryFactory() { @Override - public DdlQuery getDescribeSchemaTemplateQueryAction(@Nonnull String schemaId) { + public DdlQuery getDescribeSchemaTemplateQueryAction(String schemaId) { Assertions.fail("Should not call the query!"); return DdlQuery.NoOpDdlQuery.INSTANCE; } @@ -1370,10 +1337,9 @@ void createViewWithReferencesToSubsequentlyDefinedTableAndTypeWorks() throws Exc "CREATE TYPE AS STRUCT baz (a bigint, b bigint) "; shouldWorkWithInjectedFactory(schemaStatement, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, + Options templateProperties) { final var viewMaybe = Assertions.assertDoesNotThrow(() -> template.findViewByName("v")); assertThat(viewMaybe).isPresent(); assertThat(Assert.optionalUnchecked(viewMaybe).getDescription()).isEqualTo("SELECT * FROM bar"); @@ -1392,10 +1358,9 @@ void createIndexOnBasicSyntax() throws Exception { "CREATE INDEX i1 on bar(a, b) include (c)"; shouldWorkWithInjectedFactory(schemaStatement, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, + Options templateProperties) { final var tableMaybe = Assertions.assertDoesNotThrow(() -> template.findTableByName("bar")); assertThat(tableMaybe).isPresent(); final var table = Assert.optionalUnchecked(tableMaybe); @@ -1423,10 +1388,9 @@ void createIndexOnPredicatedView() throws Exception { "CREATE INDEX i1 on v1(b, c)"; shouldWorkWithInjectedFactory(schemaStatement, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, + Options templateProperties) { final var tableMaybe = Assertions.assertDoesNotThrow(() -> template.findTableByName("bar")); assertThat(tableMaybe).isPresent(); final var table = Assert.optionalUnchecked(tableMaybe); @@ -1467,10 +1431,9 @@ void createVectorIndex() throws Exception { "CREATE INDEX i1 on v1(b, c)"; shouldWorkWithInjectedFactory(schemaStatement, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, + Options templateProperties) { final var tableMaybe = Assertions.assertDoesNotThrow(() -> template.findTableByName("bar")); assertThat(tableMaybe).isPresent(); final var table = Assert.optionalUnchecked(tableMaybe); @@ -1511,10 +1474,9 @@ void createIndexOnBasicSyntaxComplex() throws Exception { "CREATE INDEX i1 on v1(x desc nulls first, y asc nulls last)"; shouldWorkWithInjectedFactory(schemaStatement, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, + Options templateProperties) { final var tableMaybe = Assertions.assertDoesNotThrow(() -> template.findTableByName("bar")); assertThat(tableMaybe).isPresent(); final var table = Assert.optionalUnchecked(tableMaybe); @@ -1542,10 +1504,9 @@ void createIndexOnRepeated() throws Exception { "CREATE INDEX i1 on mv1(x, p)"; shouldWorkWithInjectedFactory(schemaStatement, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, + Options templateProperties) { final var tableMaybe = Assertions.assertDoesNotThrow(() -> template.findTableByName("T")); assertThat(tableMaybe).isPresent(); final var table = Assert.optionalUnchecked(tableMaybe); @@ -1572,10 +1533,9 @@ void createIndexOnRepeatedUsingMatViewSyntax() throws Exception { "CREATE INDEX mv1 AS SELECT SQ.x, t.p from T AS t, (select M.x from t.a AS M) SQ order by SQ.x, t.p "; shouldWorkWithInjectedFactory(schemaStatement, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, + Options templateProperties) { final var tableMaybe = Assertions.assertDoesNotThrow(() -> template.findTableByName("T")); assertThat(tableMaybe).isPresent(); final var table = Assert.optionalUnchecked(tableMaybe); @@ -1603,10 +1563,9 @@ void createIndexOnAggregate() throws Exception { "CREATE INDEX i1 on mv1(a, b) include (S)"; shouldWorkWithInjectedFactory(schemaStatement, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, - @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, + Options templateProperties) { final var tableMaybe = Assertions.assertDoesNotThrow(() -> template.findTableByName("T")); assertThat(tableMaybe).isPresent(); final var table = Assert.optionalUnchecked(tableMaybe); @@ -1624,8 +1583,7 @@ public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplat }); } - @Nonnull - private static String makeColumnDefinition(@Nonnull final List columns, boolean isTable) { + private static String makeColumnDefinition(final List columns, boolean isTable) { StringBuilder columnStatement = new StringBuilder("("); int pos = 0; for (String col : columns) { @@ -1642,8 +1600,7 @@ private static String makeColumnDefinition(@Nonnull final List columns, return columnStatement.append(")").toString(); } - @Nonnull - private static List chooseIndexColumns(@Nonnull final List columns, @Nonnull final IntPredicate indexChoice) { + private static List chooseIndexColumns(final List columns, final IntPredicate indexChoice) { //choose every other column return IntStream.range(0, columns.size()) .filter(indexChoice) @@ -1651,7 +1608,7 @@ private static List chooseIndexColumns(@Nonnull final List colum .collect(Collectors.toList()); } - private static void assertColumnsMatch(@Nonnull final DdlTestUtil.ParsedType type, @Nonnull final List expectedColumns) { + private static void assertColumnsMatch(final DdlTestUtil.ParsedType type, final List expectedColumns) { Assertions.assertNotNull(type, "No type found!"); List columnStrings = type.getColumnStrings(); List expectedColStrings = IntStream.range(0, expectedColumns.size()) @@ -1660,7 +1617,7 @@ private static void assertColumnsMatch(@Nonnull final DdlTestUtil.ParsedType typ Assertions.assertEquals(expectedColStrings, columnStrings, "Incorrect columns for type <" + type.getName() + ">"); } - private static void checkColumnNullability(@Nonnull final SchemaTemplate template, int sqlType, boolean isNullable) { + private static void checkColumnNullability(final SchemaTemplate template, int sqlType, boolean isNullable) { Assertions.assertInstanceOf(RecordLayerSchemaTemplate.class, template); Assertions.assertEquals(1, ((RecordLayerSchemaTemplate) template).getTables().size(), "should have only 1 table"); final var table = ((RecordLayerSchemaTemplate) template).findTableByName("bar"); @@ -1677,8 +1634,7 @@ private static void checkColumnNullability(@Nonnull final SchemaTemplate templat Assertions.assertEquals(sqlType, maybeNullableArrayColumn.get().getDataType().getJdbcSqlCode()); } - @Nonnull - private static String replaceLast(@Nonnull final String str, final char oldChar, @Nonnull final String replacement) { + private static String replaceLast(final String str, final char oldChar, final String replacement) { if (str.isEmpty()) { return str; } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/DdlTestUtil.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/DdlTestUtil.java index 7a6d7ae4560..40bae0dafbe 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/DdlTestUtil.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/DdlTestUtil.java @@ -38,8 +38,8 @@ import com.google.protobuf.DescriptorProtos; import org.assertj.core.api.Assertions; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; + import java.net.URI; import java.sql.SQLException; import java.util.ArrayList; @@ -52,18 +52,16 @@ public class DdlTestUtil { - @Nonnull - static PlanContext createVanillaPlanContext(@Nonnull final EmbeddedRelationalConnection connection, - @Nonnull final String schemaTemplateName, - @Nonnull final String databaseUri) throws RelationalException { + static PlanContext createVanillaPlanContext(final EmbeddedRelationalConnection connection, + final String schemaTemplateName, + final String databaseUri) throws RelationalException { return createVanillaPlanContext(connection, schemaTemplateName, databaseUri, PreparedParams.empty()); } - @Nonnull - static PlanContext createVanillaPlanContext(@Nonnull final EmbeddedRelationalConnection connection, - @Nonnull final String schemaTemplateName, - @Nonnull final String databaseUri, - @Nonnull final PreparedParams preparedParams) throws RelationalException { + static PlanContext createVanillaPlanContext(final EmbeddedRelationalConnection connection, + final String schemaTemplateName, + final String databaseUri, + final PreparedParams preparedParams) throws RelationalException { final var schemaTemplate = connection.getSchemaTemplate().unwrap(RecordLayerSchemaTemplate.class).toBuilder() .setVersion(1).setName(schemaTemplateName).build(); RecordMetaDataProto.MetaData md = schemaTemplate.toRecordMetadata().toProto(); @@ -79,10 +77,9 @@ static PlanContext createVanillaPlanContext(@Nonnull final EmbeddedRelationalCon .build(); } - @Nonnull - static PlanGenerator getPlanGenerator(@Nonnull final EmbeddedRelationalConnection embeddedConnection, - @Nonnull final String schemaTemplateName, - @Nonnull final String databaseUri) throws SQLException, RelationalException { + static PlanGenerator getPlanGenerator(final EmbeddedRelationalConnection embeddedConnection, + final String schemaTemplateName, + final String databaseUri) throws SQLException, RelationalException { final var planContext = createVanillaPlanContext(embeddedConnection, schemaTemplateName, databaseUri); final var storeState = new RecordStoreState(null, Map.of()); try (var schema = embeddedConnection.getRecordLayerDatabase().loadSchema(embeddedConnection.getSchema())) { @@ -91,30 +88,27 @@ static PlanGenerator getPlanGenerator(@Nonnull final EmbeddedRelationalConnectio } } - @Nonnull - static PlanGenerator getPlanGenerator(@Nonnull final EmbeddedRelationalConnection embeddedConnection, - @Nonnull final String schemaTemplateName, - @Nonnull final String databaseUri, - @Nonnull final MetadataOperationsFactory metadataOperationsFactory) throws SQLException, RelationalException { + static PlanGenerator getPlanGenerator(final EmbeddedRelationalConnection embeddedConnection, + final String schemaTemplateName, + final String databaseUri, + final MetadataOperationsFactory metadataOperationsFactory) throws SQLException, RelationalException { return getPlanGenerator(embeddedConnection, schemaTemplateName, databaseUri, metadataOperationsFactory, PreparedParams.empty()); } - @Nonnull - static PlanGenerator getPlanGenerator(@Nonnull final EmbeddedRelationalConnection embeddedConnection, - @Nonnull final String schemaTemplateName, - @Nonnull final String databaseUri, - @Nonnull final MetadataOperationsFactory metadataOperationsFactory, - @Nonnull final PreparedParams preparedParams) throws SQLException, RelationalException { + static PlanGenerator getPlanGenerator(final EmbeddedRelationalConnection embeddedConnection, + final String schemaTemplateName, + final String databaseUri, + final MetadataOperationsFactory metadataOperationsFactory, + final PreparedParams preparedParams) throws SQLException, RelationalException { return getPlanGenerator(embeddedConnection, schemaTemplateName, databaseUri, metadataOperationsFactory, preparedParams, Options.NONE); } - @Nonnull - static PlanGenerator getPlanGenerator(@Nonnull final EmbeddedRelationalConnection embeddedConnection, - @Nonnull final String schemaTemplateName, - @Nonnull final String databaseUri, - @Nonnull final MetadataOperationsFactory metadataOperationsFactory, - @Nonnull final PreparedParams preparedParams, - @Nonnull final Options options) throws SQLException, RelationalException { + static PlanGenerator getPlanGenerator(final EmbeddedRelationalConnection embeddedConnection, + final String schemaTemplateName, + final String databaseUri, + final MetadataOperationsFactory metadataOperationsFactory, + final PreparedParams preparedParams, + final Options options) throws SQLException, RelationalException { final var planContext = PlanContext.Builder.unapply(createVanillaPlanContext(embeddedConnection, schemaTemplateName, databaseUri, preparedParams)) .withConstantActionFactory(metadataOperationsFactory).build(); final var storeState = new RecordStoreState(null, Map.of()); @@ -124,11 +118,10 @@ static PlanGenerator getPlanGenerator(@Nonnull final EmbeddedRelationalConnectio } } - @Nonnull - static PlanGenerator getPlanGenerator(@Nonnull final EmbeddedRelationalConnection embeddedConnection, - @Nonnull final String schemaTemplateName, - @Nonnull final String databaseUri, - @Nonnull final DdlQueryFactory ddlQueryFactory) throws SQLException, RelationalException { + static PlanGenerator getPlanGenerator(final EmbeddedRelationalConnection embeddedConnection, + final String schemaTemplateName, + final String databaseUri, + final DdlQueryFactory ddlQueryFactory) throws SQLException, RelationalException { final var planContext = PlanContext.Builder.unapply(createVanillaPlanContext(embeddedConnection, schemaTemplateName, databaseUri)) .withDdlQueryFactory(ddlQueryFactory).build(); final var storeState = new RecordStoreState(null, Map.of()); @@ -148,7 +141,6 @@ static PlanGenerator getPlanGenerator(@Nonnull final EmbeddedRelationalConnectio */ public static final class ParsedColumn { - @Nonnull private final DescriptorProtos.FieldDescriptorProto fieldDescriptor; /** @@ -156,7 +148,7 @@ public static final class ParsedColumn { * * @param fieldDescriptor the protobuf field descriptor to wrap */ - public ParsedColumn(@Nonnull final DescriptorProtos.FieldDescriptorProto fieldDescriptor) { + public ParsedColumn(final DescriptorProtos.FieldDescriptorProto fieldDescriptor) { this.fieldDescriptor = fieldDescriptor; } @@ -165,7 +157,6 @@ public ParsedColumn(@Nonnull final DescriptorProtos.FieldDescriptorProto fieldDe * * @return the column name */ - @Nonnull String getName() { return fieldDescriptor.getName(); } @@ -184,7 +175,6 @@ String getName() { * @return the SQL-compatible type string for this column * @throws IllegalStateException if an unexpected protobuf type or vector precision is encountered */ - @Nonnull String getType() { String type = ""; if (fieldDescriptor.hasTypeName() && !fieldDescriptor.getTypeName().isEmpty()) { @@ -257,10 +247,8 @@ String getType() { */ public static class ParsedType { - @Nonnull private final DescriptorProtos.DescriptorProto descriptor; - @Nonnull private final List columns; /** @@ -268,7 +256,7 @@ public static class ParsedType { * * @param descriptor the protobuf descriptor representing this type */ - ParsedType(@Nonnull final DescriptorProtos.DescriptorProto descriptor) { + ParsedType(final DescriptorProtos.DescriptorProto descriptor) { this.descriptor = descriptor; this.columns = parseColumns(); } @@ -278,7 +266,6 @@ public static class ParsedType { * * @return the type name */ - @Nonnull String getName() { return descriptor.getName(); } @@ -288,12 +275,10 @@ String getName() { * * @return the list of parsed columns */ - @Nonnull List getColumns() { return columns; } - @Nonnull private List parseColumns() { List cols = new ArrayList<>(descriptor.getFieldCount()); for (DescriptorProtos.FieldDescriptorProto field :descriptor.getFieldList()) { @@ -347,13 +332,10 @@ public ParsedTable(DescriptorProtos.DescriptorProto descriptor) { */ public static final class ParsedSchema { - @Nonnull private final DescriptorProtos.FileDescriptorProto schemaDescriptor; - @Nonnull private List tables; - @Nonnull private List types; /** @@ -364,7 +346,7 @@ public static final class ParsedSchema { * * @param schemaDescriptor the protobuf file descriptor representing the schema */ - ParsedSchema(@Nonnull final DescriptorProtos.FileDescriptorProto schemaDescriptor) { + ParsedSchema(final DescriptorProtos.FileDescriptorProto schemaDescriptor) { this.schemaDescriptor = schemaDescriptor; buildTypesAndTables(); @@ -375,7 +357,6 @@ public static final class ParsedSchema { * * @return the list of parsed tables */ - @Nonnull List getTables() { return tables; } @@ -385,7 +366,6 @@ List getTables() { * * @return the list of parsed types */ - @Nonnull List getTypes() { return types; } @@ -423,9 +403,8 @@ private void buildTypesAndTables() { * @param typeName the name of the type to find * @return the ParsedType if found, null otherwise */ - @Nonnull @SuppressWarnings("DataFlowIssue") - ParsedType getType(@Nonnull final String typeName) { + ParsedType getType(final String typeName) { for (final ParsedType parsedType : types) { if (parsedType.getName().equals(typeName)) { return parsedType; @@ -441,9 +420,8 @@ ParsedType getType(@Nonnull final String typeName) { * @param tableName the name of the table to find * @return the ParsedType representing the table if found, null otherwise */ - @Nonnull @SuppressWarnings("DataFlowIssue") - ParsedType getTable(@Nonnull final String tableName) { + ParsedType getTable(final String tableName) { for (final ParsedType table : tables) { if (table.getName().equals(tableName)) { return table; @@ -483,10 +461,9 @@ public String toString() { } } - @Nonnull - static String generateIndexDdlStatement(@Nonnull final IndexSyntax indexSyntax, @Nonnull final String indexName, - @Nonnull final List indexedColumns, @Nonnull final List includedColumns, - @Nonnull final String tableName) { + static String generateIndexDdlStatement(final IndexSyntax indexSyntax, final String indexName, + final List indexedColumns, final List includedColumns, + final String tableName) { final var indexedColumnsString = indexedColumns.stream().map(IndexedColumn::toString).collect(Collectors.joining(",")); final var includedColumnsString = String.join(",", includedColumns); if (indexSyntax == IndexSyntax.INDEX_AS_SYNTAX) { diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/IndexTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/IndexTest.java index b785def51d6..d07c36b13a6 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/IndexTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/IndexTest.java @@ -52,7 +52,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import javax.annotation.Nonnull; import java.util.Locale; import java.util.function.Consumer; @@ -93,7 +92,7 @@ public static void setup() { Utils.enableCascadesDebugger(); } - void shouldFailWith(@Nonnull final String query, @Nonnull final ErrorCode errorCode, @Nonnull final String errorMessage) throws Exception { + void shouldFailWith(final String query, final ErrorCode errorCode, final String errorMessage) throws Exception { connection.setAutoCommit(false); connection.getUnderlyingEmbeddedConnection().createNewTransaction(); final RelationalException ve = Assertions.assertThrows(RelationalException.class, () -> @@ -106,7 +105,7 @@ void shouldFailWith(@Nonnull final String query, @Nonnull final ErrorCode errorC connection.setAutoCommit(true); } - void shouldWorkWithInjectedFactory(@Nonnull final String query, @Nonnull final MetadataOperationsFactory metadataOperationsFactory) + void shouldWorkWithInjectedFactory(final String query, final MetadataOperationsFactory metadataOperationsFactory) throws Exception { connection.setAutoCommit(false); connection.getUnderlyingEmbeddedConnection().createNewTransaction(); @@ -117,17 +116,16 @@ void shouldWorkWithInjectedFactory(@Nonnull final String query, @Nonnull final M connection.setAutoCommit(true); } - private void indexIs(@Nonnull final String stmt, @Nonnull final KeyExpression expectedKey, @Nonnull final String indexType) throws Exception { + private void indexIs(final String stmt, final KeyExpression expectedKey, final String indexType) throws Exception { indexIs(stmt, expectedKey, indexType, index -> { }); } - private void indexIs(@Nonnull final String stmt, @Nonnull final KeyExpression expectedKey, @Nonnull final String indexType, - @Nonnull final Consumer validator) throws Exception { + private void indexIs(final String stmt, final KeyExpression expectedKey, final String indexType, + final Consumer validator) throws Exception { shouldWorkWithInjectedFactory(stmt, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull final SchemaTemplate template, - @Nonnull final Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(final SchemaTemplate template, + final Options templateProperties) { Assertions.assertInstanceOf(RecordLayerSchemaTemplate.class, template); final var recordLayerSchemaTemplate = Assert.castUnchecked(template, RecordLayerSchemaTemplate.class); Assertions.assertEquals(1, recordLayerSchemaTemplate.getTables().size(), "Incorrect number of tables"); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/SqlFunctionTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/SqlFunctionTest.java index db6e54f25ce..01c7026c670 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/SqlFunctionTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/SqlFunctionTest.java @@ -40,7 +40,6 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import javax.annotation.Nonnull; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; @@ -80,7 +79,6 @@ public static void setup() { "integer", "bigint", "double", "boolean", "string", "bytes" }; - @Nonnull public static Stream columnTypePermutations() { int numColumns = 2; final List items = List.of(validPrimitiveDataTypes); @@ -105,13 +103,13 @@ void createSqlFunctionWorksVariousTypes(List types) throws Exception { " AS SELECT * FROM T WHERE " + conditionString))); } - void shouldWorkWithInjectedFactory(@Nonnull final String query, @Nonnull final MetadataOperationsFactory metadataOperationsFactory) + void shouldWorkWithInjectedFactory(final String query, final MetadataOperationsFactory metadataOperationsFactory) throws Exception { shouldWorkWithInjectedFactory(query, PreparedParams.empty(), metadataOperationsFactory); } - void shouldWorkWithInjectedFactory(@Nonnull final String query, @Nonnull final PreparedParams preparedParams, - @Nonnull final MetadataOperationsFactory metadataOperationsFactory) + void shouldWorkWithInjectedFactory(final String query, final PreparedParams preparedParams, + final MetadataOperationsFactory metadataOperationsFactory) throws Exception { connection.setAutoCommit(false); connection.getUnderlyingEmbeddedConnection().createNewTransaction(); @@ -121,19 +119,16 @@ void shouldWorkWithInjectedFactory(@Nonnull final String query, @Nonnull final P connection.setAutoCommit(true); } - @Nonnull - SchemaTemplate ddl(@Nonnull final String sql) throws Exception { + SchemaTemplate ddl(final String sql) throws Exception { return ddl(sql, PreparedParams.empty()); } - @Nonnull - SchemaTemplate ddl(@Nonnull final String sql, @Nonnull final PreparedParams preparedParams) throws Exception { + SchemaTemplate ddl(final String sql, final PreparedParams preparedParams) throws Exception { final AtomicReference t = new AtomicReference<>(); shouldWorkWithInjectedFactory(sql, preparedParams, new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull final SchemaTemplate template, - @Nonnull final Options ignored) { + public ConstantAction getSaveSchemaTemplateConstantAction(final SchemaTemplate template, + final Options ignored) { t.set(template); return txn -> { }; diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/package-info.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/package-info.java new file mode 100644 index 00000000000..8f537a9dce6 --- /dev/null +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/package-info.java @@ -0,0 +1,24 @@ +/* + * package-info.java + * + * This source file is part of the FoundationDB open source project + * + * Copyright 2015-2025 Apple Inc. and the FoundationDB project authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@NullMarked +package com.apple.foundationdb.relational.api.ddl; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/package-info.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/package-info.java new file mode 100644 index 00000000000..f5cc4697a7e --- /dev/null +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/package-info.java @@ -0,0 +1,24 @@ +/* + * package-info.java + * + * This source file is part of the FoundationDB open source project + * + * Copyright 2021-2025 Apple Inc. and the FoundationDB project authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@NullMarked +package com.apple.foundationdb.relational.api; + +import org.jspecify.annotations.NullMarked; From 44b7042dccccb67b3ff9e9c25c89ff70d248229b Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Fri, 28 Aug 2026 18:31:33 +0200 Subject: [PATCH 02/42] Mechanical jspecify swap: fdb-relational-core query engine packages --- .../recordlayer/query/AstNormalizer.java | 120 ++- .../query/CaseInsensitiveCharStream.java | 5 +- .../recordlayer/query/CatalogKey.java | 18 +- .../recordlayer/query/ColumnarValue.java | 30 +- .../recordlayer/query/CopyPlan.java | 91 +-- .../query/EphemeralExpression.java | 8 +- .../recordlayer/query/Expression.java | 115 +-- .../recordlayer/query/Expressions.java | 68 +- .../recordlayer/query/FieldValueTrieNode.java | 36 +- .../recordlayer/query/Identifier.java | 29 +- .../recordlayer/query/Literals.java | 40 +- .../recordlayer/query/LiteralsUtils.java | 14 +- .../recordlayer/query/LogicalOperator.java | 177 ++--- .../query/LogicalOperatorCatalog.java | 26 +- .../recordlayer/query/LogicalOperators.java | 27 +- .../query/LogicalPlanFragment.java | 53 +- .../recordlayer/query/LogicalQuery.java | 6 +- .../query/MutablePlanGenerationContext.java | 88 +-- .../NormalizedQueryExecutionContext.java | 32 +- .../query/OfflineStoredQueriesProcessor.java | 52 +- .../recordlayer/query/OptionsUtils.java | 14 +- .../recordlayer/query/OrderByExpression.java | 31 +- .../recordlayer/query/OrderedLiteral.java | 46 +- .../recordlayer/query/ParseHelpers.java | 34 +- .../recordlayer/query/ParseTreeInfoImpl.java | 16 +- .../relational/recordlayer/query/Plan.java | 42 +- .../recordlayer/query/PlanContext.java | 85 +-- .../recordlayer/query/PlanGenerator.java | 107 ++- .../recordlayer/query/PlanValidator.java | 32 +- .../query/PlannerConfiguration.java | 28 +- .../recordlayer/query/PreparedParams.java | 35 +- .../recordlayer/query/ProceduralPlan.java | 17 +- .../query/QueryExecutionContext.java | 11 +- .../recordlayer/query/QueryParser.java | 27 +- .../recordlayer/query/QueryPlan.java | 177 ++--- .../recordlayer/query/SemanticAnalyzer.java | 235 +++--- .../relational/recordlayer/query/Star.java | 57 +- .../recordlayer/query/StringTrieNode.java | 7 +- .../recordlayer/query/TautologicalValue.java | 33 +- .../query/WindowSpecExpression.java | 23 +- .../query/cache/AbstractCache.java | 65 +- .../query/cache/MultiStageCache.java | 103 +-- .../query/cache/PhysicalPlanEquivalence.java | 17 +- .../query/cache/QueryCacheKey.java | 21 +- .../query/cache/RelationalPlanCache.java | 17 +- .../recordlayer/query/cache/package-info.java | 3 + .../ddl/MaterializedViewIndexGenerator.java | 76 +- .../query/ddl/OnSourceIndexGenerator.java | 66 +- .../recordlayer/query/ddl/package-info.java | 3 + .../query/functions/CompiledSqlFunction.java | 51 +- .../query/functions/SqlFunctionCatalog.java | 15 +- .../functions/SqlFunctionCatalogImpl.java | 29 +- .../functions/UserDefinedFunctionBuilder.java | 27 +- .../functions/UserDefinedFunctionCatalog.java | 12 +- .../UserDefinedMacroFunctionBuilder.java | 30 +- .../WithPlanGenerationSideEffects.java | 4 - .../query/functions/package-info.java | 3 + .../recordlayer/query/package-info.java | 3 + .../query/visitors/BaseVisitor.java | 699 ++++++------------ .../query/visitors/DdlVisitor.java | 148 ++-- .../query/visitors/DelegatingVisitor.java | 693 ++++++----------- .../query/visitors/ExpressionVisitor.java | 262 +++---- .../query/visitors/IdentifierVisitor.java | 34 +- .../query/visitors/MetadataPlanVisitor.java | 25 +- .../query/visitors/QueryVisitor.java | 126 ++-- .../query/visitors/TypedVisitor.java | 642 ++++++---------- .../query/visitors/package-info.java | 3 + .../recordlayer/query/AstNormalizerTests.java | 205 +++-- .../query/CaseSensitivityQueryTests.java | 4 +- .../query/DelegatingVisitorTest.java | 74 +- .../recordlayer/query/ExpressionTests.java | 36 +- .../recordlayer/query/LiteralsTests.java | 8 +- .../recordlayer/query/QueryTestUtils.java | 6 +- .../recordlayer/query/QueryTypeTests.java | 4 +- .../recordlayer/query/StandardQueryTests.java | 18 +- .../query/TemporaryFunctionTests.java | 7 +- .../query/TransactionBoundQueryTest.java | 13 +- .../query/cache/ConcurrentCacheTests.java | 28 +- .../query/cache/ConstraintValidityTests.java | 44 +- .../query/cache/MultiStageCacheTests.java | 38 +- .../query/cache/NoOpMetricCollector.java | 7 +- .../cache/PhysicalPlanEquivalenceTests.java | 15 - .../query/cache/RelationalPlanCacheTests.java | 122 +-- .../cache/ValueSpecificConstraintTests.java | 14 +- .../recordlayer/query/cache/package-info.java | 24 + .../functions/CompilableSqlFunctionTest.java | 4 - .../query/functions/IncarnationTest.java | 4 +- .../UserDefinedMacroFunctionBuilderTest.java | 7 +- .../query/functions/package-info.java | 24 + .../recordlayer/query/package-info.java | 24 + 90 files changed, 2128 insertions(+), 3871 deletions(-) create mode 100644 fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/package-info.java create mode 100644 fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/functions/package-info.java create mode 100644 fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/package-info.java diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizer.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizer.java index c3555a6d11f..2f7bcdce1fd 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizer.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizer.java @@ -50,9 +50,7 @@ import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.RuleNode; import org.antlr.v4.runtime.tree.TerminalNode; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import javax.annotation.concurrent.NotThreadSafe; import java.sql.Array; import java.sql.ResultSet; @@ -108,7 +106,6 @@ public final class AstNormalizer extends RelationalParserBaseVisitor { private final Supplier parameterHashSupplier; - @Nonnull private final StringBuilder sqlCanonicalizer; private final boolean caseSensitive; @@ -127,19 +124,14 @@ public final class AstNormalizer extends RelationalParserBaseVisitor { */ private boolean allowLiteralAddition; - @Nonnull private final NormalizedQueryExecutionContext.Builder queryHasherContextBuilder; - @Nonnull private final PreparedParams preparedStatementParameters; - @Nonnull private final Set queryCachingFlags; - @Nonnull private final Options.Builder queryOptions; - @Nonnull private static Map, Function> literalNodes = new HashMap<>(); static { @@ -153,8 +145,8 @@ public final class AstNormalizer extends RelationalParserBaseVisitor { literalNodes.put(RelationalParser.NegativeDecimalConstantContext.class, context -> ParseHelpers.parseDecimal(context.getText())); } - private AstNormalizer(@Nonnull final PreparedParams preparedStatementParameters, boolean caseSensitive, - @Nonnull final PlanHashable.PlanHashMode currentPlanHashMode, boolean forExplain) { + private AstNormalizer(final PreparedParams preparedStatementParameters, boolean caseSensitive, + final PlanHashable.PlanHashMode currentPlanHashMode, boolean forExplain) { parameterHash = Hashing.murmur3_32_fixed().newHasher().putInt("ParameterHash".hashCode()); parameterHashSupplier = Suppliers.memoize(() -> parameterHash.hash().asInt())::get; sqlCanonicalizer = new StringBuilder(); @@ -169,7 +161,7 @@ private AstNormalizer(@Nonnull final PreparedParams preparedStatementParameters, } @Override - public Void visitChildren(@Nonnull RuleNode node) { + public Void visitChildren(RuleNode node) { if (literalNodes.containsKey(node.getClass())) { final var ruleContext = (ParserRuleContext) node; processScalarLiteral(literalNodes.get(node.getClass()).apply(ruleContext), ruleContext.getStart().getTokenIndex()); @@ -184,7 +176,7 @@ public Void visitChildren(@Nonnull RuleNode node) { } @Override - public Void visitTerminal(@Nonnull TerminalNode node) { + public Void visitTerminal(TerminalNode node) { final var token = node.getSymbol(); if (token.getType() != Token.EOF) { // @@ -209,7 +201,7 @@ public Object visitCreateTempFunction(final RelationalParser.CreateTempFunctionC } @Override - public Value visitUid(@Nonnull RelationalParser.UidContext ctx) { + public Value visitUid(RelationalParser.UidContext ctx) { String uid = SemanticAnalyzer.normalizeString(ctx.getText(), caseSensitive); sqlCanonicalizer.append("\"").append(uid).append("\"").append(" "); return null; @@ -220,34 +212,30 @@ public int getParameterHash() { return parameterHashSupplier.get(); } - @Nonnull public String getCanonicalSqlString() { return sqlCanonicalizer.toString(); } - @Nonnull public Set getQueryCachingFlags() { return queryCachingFlags; } - @Nonnull public Options getQueryOptions() { return queryOptions.build(); } - @Nonnull public QueryExecutionContext getQueryExecutionParameters() { queryHasherContextBuilder.setParameterHash(getParameterHash()); return queryHasherContextBuilder.build(); } @Override - public Void visitFullDescribeStatement(@Nonnull RelationalParser.FullDescribeStatementContext ctx) { + public Void visitFullDescribeStatement(RelationalParser.FullDescribeStatementContext ctx) { throw new RelationalException("Explain/Describe statement should not appear at the parser level", ErrorCode.INTERNAL_ERROR).toUncheckedWrappedException(); } @Override - public Void visitLimitClause(@Nonnull RelationalParser.LimitClauseContext ctx) { + public Void visitLimitClause(RelationalParser.LimitClauseContext ctx) { if (ctx.offset != null) { // Owing to TODO Assert.failUnchecked(ErrorCode.UNSUPPORTED_QUERY, "OFFSET clause is not supported."); @@ -264,7 +252,7 @@ public Void visitLimitClauseAtom(RelationalParser.LimitClauseAtomContext ctx) { } @Override - public Object visitQuery(@Nonnull RelationalParser.QueryContext ctx) { + public Object visitQuery(RelationalParser.QueryContext ctx) { if (queryCachingFlags.isEmpty()) { queryCachingFlags.add(NormalizationResult.QueryCachingFlags.IS_DQL_STATEMENT); } @@ -276,7 +264,7 @@ public Object visitQuery(@Nonnull RelationalParser.QueryContext ctx) { } @Override - public RelationalExpression visitStatementOptions(@Nonnull RelationalParser.StatementOptionsContext ctx) { + public RelationalExpression visitStatementOptions(RelationalParser.StatementOptionsContext ctx) { for (final var opt : ctx.statementOption()) { visit(opt); } @@ -284,7 +272,7 @@ public RelationalExpression visitStatementOptions(@Nonnull RelationalParser.Stat } @Override - public Object visitStatementOption(@Nonnull RelationalParser.StatementOptionContext ctx) { + public Object visitStatementOption(RelationalParser.StatementOptionContext ctx) { try { if (ctx.NOCACHE() != null) { queryCachingFlags.add(NormalizationResult.QueryCachingFlags.WITH_NO_CACHE_OPTION); @@ -305,7 +293,7 @@ public Object visitStatementOption(@Nonnull RelationalParser.StatementOptionCont } @Override - public Object visitDdlStatement(@Nonnull RelationalParser.DdlStatementContext ctx) { + public Object visitDdlStatement(RelationalParser.DdlStatementContext ctx) { queryCachingFlags.add(NormalizationResult.QueryCachingFlags.IS_DDL_STATEMENT); return visitChildren(ctx); } @@ -329,19 +317,19 @@ public Object visitDeleteStatement(final RelationalParser.DeleteStatementContext } @Override - public Object visitAdministrationStatement(@Nonnull RelationalParser.AdministrationStatementContext ctx) { + public Object visitAdministrationStatement(RelationalParser.AdministrationStatementContext ctx) { queryCachingFlags.add(NormalizationResult.QueryCachingFlags.IS_ADMIN_STATEMENT); return visitChildren(ctx); } @Override - public Object visitUtilityStatement(@Nonnull RelationalParser.UtilityStatementContext ctx) { + public Object visitUtilityStatement(RelationalParser.UtilityStatementContext ctx) { queryCachingFlags.add(NormalizationResult.QueryCachingFlags.IS_UTILITY_STATEMENT); return visitChildren(ctx); } @Override - public Void visitContinuationAtom(@Nonnull RelationalParser.ContinuationAtomContext ctx) { + public Void visitContinuationAtom(RelationalParser.ContinuationAtomContext ctx) { allowLiteralAddition = false; if (ctx.bytesLiteral() != null) { final var continuation = ParseHelpers.parseBytes(ctx.bytesLiteral().getText()); @@ -360,7 +348,7 @@ public Void visitContinuationAtom(@Nonnull RelationalParser.ContinuationAtomCont @Override @SuppressWarnings("PMD.CompareObjectsWithEquals") // deliberate use of pointer equality - public Void visitScalarFunctionCall(@Nonnull RelationalParser.ScalarFunctionCallContext ctx) { + public Void visitScalarFunctionCall(RelationalParser.ScalarFunctionCallContext ctx) { final var functionName = ctx.scalarFunctionName().getText(); boolean skipFirstFunctionArgument = "JAVA_CALL".equals(SemanticAnalyzer.normalizeString(functionName, false)); for (int i = 0; i < ctx.getChildCount(); i++) { @@ -383,7 +371,7 @@ public Void visitScalarFunctionCall(@Nonnull RelationalParser.ScalarFunctionCall } @Override - public Object visitPreparedStatementParameter(@Nonnull RelationalParser.PreparedStatementParameterContext ctx) { + public Object visitPreparedStatementParameter(RelationalParser.PreparedStatementParameterContext ctx) { Object param; if (ctx.QUESTION() != null) { final int currentUnnamedParameterIndex = preparedStatementParameters.currentUnnamedParamIndex(); @@ -436,7 +424,7 @@ public Object visitPreparedStatementParameter(@Nonnull RelationalParser.Prepared } @Override - public Object visitInPredicate(@Nonnull RelationalParser.InPredicateContext ctx) { + public Object visitInPredicate(RelationalParser.InPredicateContext ctx) { if (ctx.NOT() != null) { ctx.NOT().accept(this); } @@ -492,7 +480,7 @@ public Object visitInPredicate(@Nonnull RelationalParser.InPredicateContext ctx) * * @param expressions the items of the {@code IN} list */ - private void rejectNullItems(@Nonnull final RelationalParser.ExpressionsContext expressions) { + private void rejectNullItems(final RelationalParser.ExpressionsContext expressions) { for (final var expression : expressions.expression()) { Assert.thatUnchecked(!isNullLiteral(expression), ErrorCode.WRONG_OBJECT_TYPE, "NULL values are not allowed in the IN list"); @@ -507,7 +495,7 @@ private void rejectNullItems(@Nonnull final RelationalParser.ExpressionsContext * @param tree one item of an {@code IN} list * @return {@code true} if the item is a bare {@code NULL} literal */ - private static boolean isNullLiteral(@Nonnull final ParseTree tree) { + private static boolean isNullLiteral(final ParseTree tree) { var current = tree; while (!(current instanceof RelationalParser.NullLiteralContext) && current.getChildCount() == 1) { current = current.getChild(0); @@ -516,7 +504,7 @@ private static boolean isNullLiteral(@Nonnull final ParseTree tree) { } @Override - public Object visitExecuteContinuationStatement(@Nonnull RelationalParser.ExecuteContinuationStatementContext ctx) { + public Object visitExecuteContinuationStatement(RelationalParser.ExecuteContinuationStatementContext ctx) { queryCachingFlags.add(NormalizationResult.QueryCachingFlags.IS_EXECUTE_CONTINUATION_STATEMENT); queryCachingFlags.add(NormalizationResult.QueryCachingFlags.WITH_NO_CACHE_OPTION); if (ctx.statementOptions() != null) { @@ -537,7 +525,7 @@ public Object visitCopyImportStatement(final RelationalParser.CopyImportStatemen return visitChildren(ctx); } - private void processArrayParameter(@Nonnull final Array param, @Nullable Integer unnamedParameterIndex, + private void processArrayParameter(final Array param, @Nullable Integer unnamedParameterIndex, @Nullable String parameterName, final int tokenIndex) { try { queryHasherContextBuilder.getLiteralsBuilder().startArrayLiteral(); @@ -554,7 +542,7 @@ private void processArrayParameter(@Nonnull final Array param, @Nullable Integer } } - private void processStructParameter(@Nonnull final Struct param, @Nullable Integer unnamedParameterIndex, + private void processStructParameter(final Struct param, @Nullable Integer unnamedParameterIndex, @Nullable String parameterName, final int tokenIndex) { try { queryHasherContextBuilder.getLiteralsBuilder().startStructLiteral(); @@ -569,7 +557,7 @@ private void processStructParameter(@Nonnull final Struct param, @Nullable Integ } } - private void processParameterValue(@Nonnull final Object parameterValue, + private void processParameterValue(final Object parameterValue, @Nullable Integer unnamedParameterIndex, @Nullable String parameterName, final int tokenIndex) { @@ -582,21 +570,21 @@ private void processParameterValue(@Nonnull final Object parameterValue, } } - private void processScalarLiteral(@Nonnull final Object literal, final int tokenIndex) { + private void processScalarLiteral(final Object literal, final int tokenIndex) { processLiteral(literal, tokenIndex, null, null); } - private void processUnnamedParameter(@Nonnull final Object literal, final int unnamedParameterIndex, + private void processUnnamedParameter(final Object literal, final int unnamedParameterIndex, final int tokenIndex) { processLiteral(literal, tokenIndex, unnamedParameterIndex, null); } - private void processNamedParameter(@Nonnull final Object literal, @Nonnull final String parameterName, + private void processNamedParameter(final Object literal, final String parameterName, final int tokenIndex) { processLiteral(literal, tokenIndex, null, parameterName); } - private void processLiteral(@Nonnull final Object literal, final int tokenIndex, + private void processLiteral(final Object literal, final int tokenIndex, @Nullable final Integer unnamedParameterIndex, @Nullable final String parameterName) { if (allowLiteralAddition) { queryHasherContextBuilder.getLiteralsBuilder() @@ -617,11 +605,10 @@ private void processLiteral(@Nonnull final Object literal, final int tokenIndex, * @param currentPlanHashMode The mode used to calculate the hash of the query plan * @return The query parse tree along with contextual information required for planning and executing it. */ - @Nonnull - public static NormalizationResult normalizeQuery(@Nonnull final PlanContext context, - @Nonnull final String query, + public static NormalizationResult normalizeQuery(final PlanContext context, + final String query, boolean isCaseSensitive, - @Nonnull final PlanHashable.PlanHashMode currentPlanHashMode) throws RelationalException { + final PlanHashable.PlanHashMode currentPlanHashMode) throws RelationalException { // lexing, parsing, and normalization are profiled through the metric collector. final var metricCollector = context.getMetricsCollector(); final var parseTreeInfo = metricCollector.clock(RelationalMetric.RelationalEvent.LEX_PARSE, @@ -638,15 +625,14 @@ public static NormalizationResult normalizeQuery(@Nonnull final PlanContext cont )); } - @Nonnull @VisibleForTesting - public static NormalizationResult normalizeAst(@Nonnull final SchemaTemplate schemaTemplate, - @Nonnull final ParseTreeInfoImpl parseTreeInfo, - @Nonnull final PreparedParams preparedStatementParameters, - @Nonnull final PlannerConfiguration plannerConfiguration, + public static NormalizationResult normalizeAst(final SchemaTemplate schemaTemplate, + final ParseTreeInfoImpl parseTreeInfo, + final PreparedParams preparedStatementParameters, + final PlannerConfiguration plannerConfiguration, boolean caseSensitive, - @Nonnull final PlanHashable.PlanHashMode currentPlanHashMode, - @Nonnull final String query) throws RelationalException { + final PlanHashable.PlanHashMode currentPlanHashMode, + final String query) throws RelationalException { final var astNormalizer = new AstNormalizer(preparedStatementParameters, caseSensitive, currentPlanHashMode, parseTreeInfo.getQueryType() == ParseTreeInfo.QueryType.DESCRIBE_QUERY); astNormalizer.visit(parseTreeInfo.getRootContext()); final var recordLayerSchemaTemplate = Assert.castUnchecked(schemaTemplate, RecordLayerSchemaTemplate.class); @@ -696,8 +682,8 @@ public static NormalizationResult normalizeAst(@Nonnull final SchemaTemplate sch // from connection-level options, before the query text is even parsed. This method bridges that gap: for any // planner-affecting option that can be asserted at query level, it overrides the corresponding field in the // connection-level PlannerConfiguration so that the cache key correctly reflects what was requested in the SQL. - private static PlannerConfiguration getQuerySpecificPlannerConfig(@Nonnull final PlannerConfiguration plannerConfiguration, - @Nonnull final Options options) { + private static PlannerConfiguration getQuerySpecificPlannerConfig(final PlannerConfiguration plannerConfiguration, + final Options options) { if (options.getOption(Options.Name.PLAN_RIGHT_DEEP)) { return plannerConfiguration.withPlanRightDeep(true); } @@ -726,34 +712,27 @@ public enum QueryCachingFlags { WITH_NO_CACHE_OPTION; } - @Nonnull private final String schemaTemplateName; - @Nonnull private final QueryCacheKey queryCacheKey; - @Nonnull private final QueryExecutionContext queryExecutionContext; - @Nonnull private final ParseTree parseTree; - @Nonnull private final Set queryCachingFlags; - @Nonnull private final Options queryOptions; - @Nonnull private final String query; - public NormalizationResult(@Nonnull final String schemaTemplateName, - @Nonnull final QueryCacheKey queryCacheKey, - @Nonnull final QueryExecutionContext queryExecutionContext, - @Nonnull final ParseTree parseTree, - @Nonnull final Set queryCachingFlags, - @Nonnull final Options queryOptions, - @Nonnull final String query) { + public NormalizationResult(final String schemaTemplateName, + final QueryCacheKey queryCacheKey, + final QueryExecutionContext queryExecutionContext, + final ParseTree parseTree, + final Set queryCachingFlags, + final Options queryOptions, + final String query) { this.schemaTemplateName = schemaTemplateName; this.queryCacheKey = queryCacheKey; this.queryExecutionContext = queryExecutionContext; @@ -763,37 +742,30 @@ public NormalizationResult(@Nonnull final String schemaTemplateName, this.query = query; } - @Nonnull public String getSchemaTemplateName() { return schemaTemplateName; } - @Nonnull public QueryCacheKey getQueryCacheKey() { return queryCacheKey; } - @Nonnull public QueryExecutionContext getQueryExecutionContext() { return queryExecutionContext; } - @Nonnull public ParseTree getParseTree() { return parseTree; } - @Nonnull public Set getQueryCachingFlags() { return queryCachingFlags; } - @Nonnull public Options getQueryOptions() { return queryOptions; } - @Nonnull public String getQuery() { return query; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CaseInsensitiveCharStream.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CaseInsensitiveCharStream.java index ab6a41e5f9e..cf7b26d7bf5 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CaseInsensitiveCharStream.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CaseInsensitiveCharStream.java @@ -26,9 +26,6 @@ import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.IntStream; import org.antlr.v4.runtime.misc.Interval; - -import javax.annotation.Nonnull; - /** * A {@link IntStream} stream, that enables allows a case-sensitive {@link org.antlr.v4.runtime.Lexer} * to become case-insensitive by upper-casing the stream of symbols arriving to it. @@ -39,7 +36,7 @@ public class CaseInsensitiveCharStream implements CharStream { /** Character stream. */ private final CharStream underlying; - public CaseInsensitiveCharStream(@Nonnull final String sql) { + public CaseInsensitiveCharStream(final String sql) { this.underlying = CharStreams.fromString(sql); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CatalogKey.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CatalogKey.java index b46d2e1fe59..9962d625eac 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CatalogKey.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CatalogKey.java @@ -26,8 +26,6 @@ import com.apple.foundationdb.record.query.plan.cascades.IndexAccessHint; import com.google.common.collect.ImmutableSet; - -import javax.annotation.Nonnull; import java.util.Objects; import java.util.Set; @@ -39,14 +37,12 @@ */ @API(API.Status.EXPERIMENTAL) public final class CatalogKey { - @Nonnull private final Identifier identifier; - @Nonnull private final Set hints; - private CatalogKey(@Nonnull Identifier identifier, - @Nonnull Set hints) { + private CatalogKey(Identifier identifier, + Set hints) { this.identifier = identifier; this.hints = hints; } @@ -68,23 +64,19 @@ public int hashCode() { return Objects.hash(getIdentifier(), getHints()); } - @Nonnull - public static CatalogKey of(@Nonnull Identifier identifier, - @Nonnull Set requestedIndexes) { + public static CatalogKey of(Identifier identifier, + Set requestedIndexes) { return new CatalogKey(identifier, requestedIndexes.stream().map(IndexAccessHint::new).collect(ImmutableSet.toImmutableSet())); } - @Nonnull - public static CatalogKey of(@Nonnull Identifier identifier) { + public static CatalogKey of(Identifier identifier) { return new CatalogKey(identifier, ImmutableSet.of()); } - @Nonnull public Identifier getIdentifier() { return identifier; } - @Nonnull public Set getHints() { return hints; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ColumnarValue.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ColumnarValue.java index 1eed1f3a5e3..59a2de69f9d 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ColumnarValue.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ColumnarValue.java @@ -31,18 +31,15 @@ import com.apple.foundationdb.record.query.plan.cascades.values.Value; import com.apple.foundationdb.record.query.plan.explain.ExplainTokensWithPrecedence; import com.google.protobuf.Message; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.Set; import java.util.function.Supplier; public class ColumnarValue implements Value { - @Nonnull private final Value inner; private final int columnId; - public ColumnarValue(@Nonnull final Value inner, final int columnId) { + public ColumnarValue(final Value inner, final int columnId) { this.inner = inner; this.columnId = columnId; } @@ -51,20 +48,17 @@ public int getColumnId() { return columnId; } - @Nonnull public Value getInner() { return inner; } - @Nonnull @Override public Type getResultType() { return inner.getResultType(); } - @Nonnull @Override - public ExplainTokensWithPrecedence explain(@Nonnull final Iterable> explainSuppliers) { + public ExplainTokensWithPrecedence explain(final Iterable> explainSuppliers) { return inner.explain(explainSuppliers); } @@ -76,17 +70,15 @@ public boolean isIndexOnly() { @Nullable @Override public Object eval(@Nullable final FDBRecordStoreBase store, - @Nonnull final EvaluationContext context) { + final EvaluationContext context) { return inner.eval(store, context); } - @Nonnull @Override public Set getCorrelatedToWithoutChildren() { return inner.getCorrelatedToWithoutChildren(); } - @Nonnull @Override public Set getCorrelatedTo() { return inner.getCorrelatedTo(); @@ -102,37 +94,33 @@ public int hashCodeWithoutChildren() { return inner.hashCodeWithoutChildren(); } - @Nonnull @Override public Iterable getChildren() { return inner.getChildren(); } - @Nonnull @Override - public Value withChildren(@Nonnull final Iterable newChildren) { + public Value withChildren(final Iterable newChildren) { return new ColumnarValue(inner.withChildren(newChildren), columnId); } @Override - public int planHash(@Nonnull final PlanHashable.PlanHashMode hashMode) { + public int planHash(final PlanHashable.PlanHashMode hashMode) { return inner.planHash(hashMode); } - @Nonnull @Override - public Message toProto(@Nonnull final PlanSerializationContext serializationContext) { + public Message toProto(final PlanSerializationContext serializationContext) { return inner.toProto(serializationContext); } - @Nonnull @Override - public PValue toValueProto(@Nonnull final PlanSerializationContext serializationContext) { + public PValue toValueProto(final PlanSerializationContext serializationContext) { return inner.toValueProto(serializationContext); } @Override - public boolean semanticEquals(@Nullable final Object other, @Nonnull final AliasMap aliasMap) { + public boolean semanticEquals(@Nullable final Object other, final AliasMap aliasMap) { if (other instanceof ColumnarValue) { return inner.semanticEquals(((ColumnarValue) other).inner, aliasMap); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java index b4964b812c6..f291bfa3de2 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java @@ -69,9 +69,7 @@ import com.apple.foundationdb.relational.transactionbound.catalog.HollowStoreCatalog; import com.apple.foundationdb.relational.util.catalog.KeySpaceProvider; import com.google.protobuf.ByteString; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.net.URI; import java.sql.Array; import java.sql.SQLException; @@ -110,15 +108,12 @@ private enum CopyType { } } - @Nonnull private final CopyType copyType; - @Nonnull private final String path; private final boolean incrementIncarnation; - @Nonnull private final QueryExecutionContext queryExecutionContext; @Nullable private final byte[] continuation; @@ -133,9 +128,8 @@ private enum CopyType { * * @return a CopyPlan for exporting data */ - @Nonnull - public static CopyPlan getCopyExportAction(@Nonnull String path, - @Nonnull QueryExecutionContext queryExecutionContext, + public static CopyPlan getCopyExportAction(String path, + QueryExecutionContext queryExecutionContext, boolean incrementIncarnation) { return new CopyPlan(CopyType.EXPORT, path, incrementIncarnation, queryExecutionContext, null); } @@ -147,15 +141,14 @@ public static CopyPlan getCopyExportAction(@Nonnull String path, * * @return a CopyPlan for importing data */ - @Nonnull - public static CopyPlan getCopyImportAction(@Nonnull String path, - @Nonnull QueryExecutionContext queryExecutionContext) { + public static CopyPlan getCopyImportAction(String path, + QueryExecutionContext queryExecutionContext) { return new CopyPlan(CopyType.IMPORT, path, false, queryExecutionContext, null); } - public static CopyPlan fromContinuation(@Nonnull final com.apple.foundationdb.relational.continuation.CopyPlan protobuf, + public static CopyPlan fromContinuation(final com.apple.foundationdb.relational.continuation.CopyPlan protobuf, @Nullable final byte[] continuation, - @Nonnull final MutablePlanGenerationContext planGenerationContext) { + final MutablePlanGenerationContext planGenerationContext) { return new CopyPlan(CopyType.EXPORT, protobuf.getPath(), protobuf.getIncrementIncarnation(), @@ -163,10 +156,10 @@ public static CopyPlan fromContinuation(@Nonnull final com.apple.foundationdb.re continuation); } - private CopyPlan(@Nonnull CopyType copyType, - @Nonnull String path, + private CopyPlan(CopyType copyType, + String path, boolean incrementIncarnation, - @Nonnull QueryExecutionContext queryExecutionContext, + QueryExecutionContext queryExecutionContext, @Nullable byte[] continuation) { super("COPY " + copyType.name() + " " + path); this.copyType = copyType; @@ -183,15 +176,15 @@ public boolean isUpdatePlan() { } @Override - public Plan optimize(@Nonnull CascadesPlanner planner, - @Nonnull PlanContext planContext, - @Nonnull PlanHashable.PlanHashMode currentPlanHashMode) { + public Plan optimize(CascadesPlanner planner, + PlanContext planContext, + PlanHashable.PlanHashMode currentPlanHashMode) { // No optimization needed for COPY operations return this; } @Override - protected RelationalResultSet executeInternal(@Nonnull ExecutionContext context) throws RelationalException { + protected RelationalResultSet executeInternal(ExecutionContext context) throws RelationalException { switch (copyType) { case EXPORT: return executeExport(context); @@ -204,7 +197,7 @@ protected RelationalResultSet executeInternal(@Nonnull ExecutionContext context) @SuppressWarnings("PMD.CloseResource") // Connection/cursor not owned by this method - private RelationalResultSet executeExport(@Nonnull ExecutionContext context) throws RelationalException { + private RelationalResultSet executeExport(ExecutionContext context) throws RelationalException { try { final KeySpacePath keySpacePath = getPath(context); @@ -263,11 +256,11 @@ private RelationalResultSet executeExport(@Nonnull ExecutionContext context) thr } @Nullable - private static ArrayRow convertDataToRow(@Nonnull final ExecutionContext context, + private static ArrayRow convertDataToRow(final ExecutionContext context, @Nullable final DataInKeySpacePath data, - @Nonnull final KeySpacePathSerializer serializer, - @Nonnull final Map pathSchemaCache, - @Nonnull final StoreCatalog storeCatalog, + final KeySpacePathSerializer serializer, + final Map pathSchemaCache, + final StoreCatalog storeCatalog, final boolean incrementIncarnation) { if (data == null) { return null; @@ -306,12 +299,12 @@ private static ArrayRow convertDataToRow(@Nonnull final ExecutionContext context return new ArrayRow(new Object[] {copyDataBuilder.build().toByteArray()}); } - private static EmbeddedRelationalConnection getEmbeddedRelationalConnection(final @Nonnull ExecutionContext context) throws SQLException { + private static EmbeddedRelationalConnection getEmbeddedRelationalConnection(final ExecutionContext context) throws SQLException { return context.connection.unwrap(EmbeddedRelationalConnection.class); } @SuppressWarnings("PMD.CloseResource") // Connection not owned by this method - private RelationalResultSet executeImport(@Nonnull ExecutionContext context) throws RelationalException { + private RelationalResultSet executeImport(ExecutionContext context) throws RelationalException { try { // Ensure we have query execution context if (queryExecutionContext == null) { @@ -373,10 +366,10 @@ private RelationalResultSet executeImport(@Nonnull ExecutionContext context) thr * @return CatalogInfo if this is a new schema, null otherwise */ @Nullable - private static CatalogInfo exportCatalogInfo(@Nonnull KeySpacePath dataPath, - @Nonnull Map pathSchemaCache, - @Nonnull StoreCatalog storeCatalog, - @Nonnull Transaction transaction) throws RelationalException { + private static CatalogInfo exportCatalogInfo(KeySpacePath dataPath, + Map pathSchemaCache, + StoreCatalog storeCatalog, + Transaction transaction) throws RelationalException { // HollowStoreCatalog doesn't actually store any schema information to be copied if (storeCatalog instanceof HollowStoreCatalog) { return null; @@ -421,10 +414,10 @@ private static CatalogInfo exportCatalogInfo(@Nonnull KeySpacePath dataPath, * @param transaction the transaction to use * @param dataPath the path for entry being imported */ - private static void importCatalogInfo(@Nonnull CatalogInfo catalogInfo, - @Nonnull StoreCatalog storeCatalog, - @Nonnull Transaction transaction, - @Nonnull KeySpacePath dataPath) throws RelationalException { + private static void importCatalogInfo(CatalogInfo catalogInfo, + StoreCatalog storeCatalog, + Transaction transaction, + KeySpacePath dataPath) throws RelationalException { // Extract destination database and schema from the import path final String templateName = catalogInfo.getTemplateName(); final int templateVersion = catalogInfo.getTemplateVersion(); @@ -460,7 +453,6 @@ private static void importCatalogInfo(@Nonnull CatalogInfo catalogInfo, } } - @Nonnull private List getDataForImport() throws RelationalException { final List orderedLiterals = queryExecutionContext.getLiterals().getOrderedLiterals(); if (orderedLiterals.isEmpty()) { @@ -504,7 +496,6 @@ private List getDataForImport() throws RelationalException { ErrorCode.INVALID_PARAMETER); } - @Nonnull private static byte[] convertToBytes(@Nullable final Object element) throws RelationalException { if (element instanceof byte[]) { return (byte[]) element; @@ -517,9 +508,8 @@ private static byte[] convertToBytes(@Nullable final Object element) throws Rela ErrorCode.INVALID_PARAMETER); } - @Nonnull - private static DataInKeySpacePath deserializeData(@Nonnull final KeySpacePathSerializer serializer, - @Nonnull final CopyData proto) throws RelationalException { + private static DataInKeySpacePath deserializeData(final KeySpacePathSerializer serializer, + final CopyData proto) throws RelationalException { DataInKeySpacePath dataInKeySpacePath; try { if (!proto.hasData()) { @@ -537,9 +527,9 @@ private static DataInKeySpacePath deserializeData(@Nonnull final KeySpacePathSer return dataInKeySpacePath; } - private static int importData(@Nonnull final KeySpacePath keySpacePath, - @Nonnull final FDBRecordContext fdbContext, - @Nonnull final DataInKeySpacePath dataInKeySpacePath, + private static int importData(final KeySpacePath keySpacePath, + final FDBRecordContext fdbContext, + final DataInKeySpacePath dataInKeySpacePath, int importCount) throws RelationalException { try { keySpacePath.importData(fdbContext, Collections.singleton(dataInKeySpacePath)).join(); @@ -551,41 +541,36 @@ private static int importData(@Nonnull final KeySpacePath keySpacePath, return importCount; } - @Nonnull @Override public QueryPlanConstraint getConstraint() { return QueryPlanConstraint.noConstraint(); } @SuppressWarnings("PMD.CompareObjectsWithEquals") // we don't want to create a new instance if the queryExecutionContext is the *same* - @Nonnull @Override - public CopyPlan withExecutionContext(@Nonnull QueryExecutionContext queryExecutionContext) { + public CopyPlan withExecutionContext(QueryExecutionContext queryExecutionContext) { if (queryExecutionContext == this.queryExecutionContext) { return this; } return new CopyPlan(copyType, path, incrementIncarnation, queryExecutionContext, continuation); } - @Nonnull @Override public String explain() { return "CopyPlan(" + copyType + ", path=" + path + ", incrementIncarnation=" + incrementIncarnation + ")"; } - @Nonnull @Override public Type getResultType() { return copyType.resultType; } - @Nonnull public Integer getPlanHash() { return PlanHashable.objectsPlanHash(PlanHashable.CURRENT_FOR_CONTINUATION, BASE_HASH, copyType, path, incrementIncarnation); } - private static NonnullPair getDatabaseAndSchema(@Nonnull final KeySpacePath dataPath) throws RelationalException { + private static NonnullPair getDatabaseAndSchema(final KeySpacePath dataPath) throws RelationalException { // toPathString doesn't add the '/' at the beginning unless the root is null, but SemanticAnalyzer expects // a / at the beginning String pathString = KeySpaceUtils.toPathString(dataPath); @@ -601,7 +586,6 @@ private static NonnullPair getDatabaseAndSchema(@Nonnull final KeyS return NonnullPair.of(database.get(), uri.getRight()); } - @Nonnull private KeySpacePath getPath(final ExecutionContext context) throws RelationalException, SQLException { final StoreCatalog catalog = context.connection.unwrap(EmbeddedRelationalConnection.class).getBackingCatalog(); if (catalog instanceof KeySpaceProvider) { @@ -617,11 +601,10 @@ private KeySpacePath getPath(final ExecutionContext context) throws RelationalEx throw new RelationalException("COPY not supported for this catalog", ErrorCode.UNSUPPORTED_OPERATION); } - private static FDBRecordContext getRecordContext(@Nonnull final ExecutionContext context) throws InternalErrorException { + private static FDBRecordContext getRecordContext(final ExecutionContext context) throws InternalErrorException { return context.transaction.unwrap(RecordContextTransaction.class).getContext(); } - @Nonnull private static RelationalStructMetaData getImportResultSetMetaData() { return RelationalStructMetaData.of(DataType.StructType.from("COPY_IMPORT", List.of(DataType.StructType.Field.from("COUNT", DataType.IntegerType.notNullable(), 0)), false)); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/EphemeralExpression.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/EphemeralExpression.java index 1a54510425e..4bd2435a986 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/EphemeralExpression.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/EphemeralExpression.java @@ -23,8 +23,6 @@ import com.apple.foundationdb.annotation.API; import com.apple.foundationdb.record.query.plan.cascades.values.Value; import com.apple.foundationdb.relational.api.metadata.DataType; - -import javax.annotation.Nonnull; import java.util.Optional; /** @@ -34,17 +32,15 @@ @API(API.Status.EXPERIMENTAL) public class EphemeralExpression extends Expression { - public EphemeralExpression(@Nonnull Optional name, @Nonnull DataType dataType, @Nonnull Value expression, @Nonnull Visibility visibility) { + public EphemeralExpression(Optional name, DataType dataType, Value expression, Visibility visibility) { super(name, dataType, expression, visibility); } - @Nonnull @Override - protected Expression createNew(@Nonnull Optional newName, @Nonnull DataType newDataType, @Nonnull Value newUnderlying, @Nonnull Visibility newVisibility) { + protected Expression createNew(Optional newName, DataType newDataType, Value newUnderlying, Visibility newVisibility) { return new EphemeralExpression(newName, newDataType, newUnderlying, newVisibility); } - @Nonnull @Override public EphemeralExpression asEphemeral() { return this; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Expression.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Expression.java index 4d4a28f8491..f3a62d7e8ca 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Expression.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Expression.java @@ -52,8 +52,6 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Multimap; import com.google.common.collect.Streams; - -import javax.annotation.Nonnull; import java.util.Collection; import java.util.List; import java.util.Optional; @@ -69,13 +67,10 @@ @API(API.Status.EXPERIMENTAL) public class Expression { - @Nonnull private final Optional name; - @Nonnull private final DataType dataType; - @Nonnull private final Supplier underlying; public enum Visibility { @@ -85,45 +80,41 @@ public enum Visibility { private final Visibility visibility; - public Expression(@Nonnull Optional name, - @Nonnull DataType dataType, - @Nonnull Value expression) { + public Expression(Optional name, + DataType dataType, + Value expression) { this(name, dataType, () -> expression, Visibility.VISIBLE); } - public Expression(@Nonnull Optional name, - @Nonnull DataType dataType, - @Nonnull Value expression, - @Nonnull Visibility visibility) { + public Expression(Optional name, + DataType dataType, + Value expression, + Visibility visibility) { this(name, dataType, () -> expression, visibility); } - public Expression(@Nonnull Optional name, - @Nonnull DataType dataType, - @Nonnull Supplier valueSupplier, - @Nonnull Visibility visibility) { + public Expression(Optional name, + DataType dataType, + Supplier valueSupplier, + Visibility visibility) { this.name = name; this.dataType = dataType; this.underlying = Suppliers.memoize(valueSupplier::get); this.visibility = visibility; } - @Nonnull public Optional getName() { return name; } - @Nonnull public DataType getDataType() { return dataType; } - @Nonnull public Value getUnderlying() { return Assert.castUnchecked(underlying.get(), Value.class); } - @Nonnull public Visibility getVisibility() { return visibility; } @@ -144,28 +135,24 @@ public boolean isVisible() { * @param newVisibility the new visibility flag * @return a new expression with the given name, type, and value */ - @Nonnull - protected Expression createNew(@Nonnull Optional newName, @Nonnull DataType newDataType, @Nonnull Value newUnderlying, @Nonnull Visibility newVisibility) { + protected Expression createNew(Optional newName, DataType newDataType, Value newUnderlying, Visibility newVisibility) { return new Expression(newName, newDataType, newUnderlying, newVisibility); } - @Nonnull - public Expression withName(@Nonnull Identifier name) { + public Expression withName(Identifier name) { if (getName().isPresent() && getName().get().equals(name)) { return this; } return createNew(Optional.of(name), getDataType(), getUnderlying(), getVisibility()); } - @Nonnull - public Expression withUnderlying(@Nonnull Value underlying) { + public Expression withUnderlying(Value underlying) { if (getUnderlying().semanticEquals(underlying, AliasMap.identitiesFor(underlying.getCorrelatedTo()))) { return this; } return createNew(getName(), DataTypeUtils.toRelationalType(underlying.getResultType()), underlying, getVisibility()); } - @Nonnull public Expression clearQualifier() { if (getName().isEmpty()) { return this; @@ -177,13 +164,11 @@ public Expression clearQualifier() { return createNew(Optional.of(name.withoutQualifier()), getDataType(), getUnderlying(), getVisibility()); } - @Nonnull - public Expression withQualifier(@Nonnull final Collection qualifier) { + public Expression withQualifier(final Collection qualifier) { return replaceQualifier(ignored -> qualifier); } - @Nonnull - public Expression replaceQualifier(@Nonnull Function, Collection> replaceFunc) { + public Expression replaceQualifier(Function, Collection> replaceFunc) { if (getName().isEmpty()) { return this; } @@ -195,8 +180,7 @@ public Expression replaceQualifier(@Nonnull Function, Collect return createNew(Optional.of(newNameMaybe), getDataType(), getUnderlying(), getVisibility()); } - @Nonnull - public Expression withQualifier(@Nonnull final Optional qualifier) { + public Expression withQualifier(final Optional qualifier) { if (getName().isEmpty()) { return this; } @@ -218,12 +202,10 @@ public boolean isAggregate() { return underlying instanceof AggregateValue && !(underlying instanceof RecordConstructorValue); } - @Nonnull - public NamedArgumentExpression toNamedArgument(@Nonnull final Identifier name) { + public NamedArgumentExpression toNamedArgument(final Identifier name) { return new NamedArgumentExpression(Optional.of(name), dataType, getUnderlying(), getVisibility()); } - @Nonnull public NamedArgumentExpression toNamedArgument() { return toNamedArgument(Assert.optionalUnchecked(getName())); } @@ -236,9 +218,8 @@ public boolean isNamedArgument() { * Returns this expression rewritten in terms of the given value, simplifying both sides on the way. See * {@link #pullUp(Value, Value, AliasMap, CorrelationIdentifier, Set)} for details. */ - @Nonnull - public Expression pullUp(@Nonnull Value value, @Nonnull CorrelationIdentifier correlationIdentifier, - @Nonnull Set constantAliases) { + public Expression pullUp(Value value, CorrelationIdentifier correlationIdentifier, + Set constantAliases) { final AliasMap aliasMap = AliasMap.identitiesFor(value.getCorrelatedTo()); final Value simplifiedValue = value.simplify(EvaluationContext.empty(), aliasMap, constantAliases); final Value simplifiedUnderlying = @@ -267,10 +248,9 @@ public Expression pullUp(@Nonnull Value value, @Nonnull CorrelationIdentifier co * @param constantAliases the aliases that are considered constant * @return {@code value}, rewritten in terms of {@code other} */ - @Nonnull - static Value pullUp(@Nonnull Value value, @Nonnull Value other, @Nonnull AliasMap aliasMap, - @Nonnull CorrelationIdentifier correlationIdentifier, - @Nonnull Set constantAliases) { + static Value pullUp(Value value, Value other, AliasMap aliasMap, + CorrelationIdentifier correlationIdentifier, + Set constantAliases) { // Walk the value, “offering” every sub-value for replacement in terms of the reference value. return Assert.notNullUnchecked(value.replace( subExpression -> { @@ -296,8 +276,8 @@ static Value pullUp(@Nonnull Value value, @Nonnull Value other, @Nonnull AliasMa )); } - public boolean canBeDerivedFrom(@Nonnull final Expression expression, - @Nonnull final Set constantAliases) { + public boolean canBeDerivedFrom(final Expression expression, + final Set constantAliases) { final var value = expression.getUnderlying(); final var aliasMap = AliasMap.identitiesFor(value.getCorrelatedTo()); final var simplifiedValue = value.simplify(EvaluationContext.empty(), aliasMap, constantAliases); @@ -316,8 +296,7 @@ public boolean canBeDerivedFrom(@Nonnull final Expression expression, * @return a new {@link Expressions} list where each {@link Expression} internal {@link Value} with {@link LiteralValue}s * instead of any {@link ConstantObjectValue}s. */ - @Nonnull - public Expressions dereferenced(@Nonnull Literals literals) { + public Expressions dereferenced(Literals literals) { return Expressions.ofSingle(withUnderlying(Assert.notNullUnchecked(getUnderlying().replace(value -> { if (value instanceof ConstantObjectValue) { final ConstantObjectValue constantObjectValue = (ConstantObjectValue) value; @@ -327,7 +306,6 @@ public Expressions dereferenced(@Nonnull Literals literals) { })))); } - @Nonnull public Expression asHidden() { if (!isVisible()) { return this; @@ -335,7 +313,6 @@ public Expression asHidden() { return createNew(getName(), getDataType(), getUnderlying(), Visibility.HIDDEN); } - @Nonnull public EphemeralExpression asEphemeral() { Verify.verify(getName().isPresent()); return new EphemeralExpression(getName(), getDataType(), getUnderlying(), getVisibility()); @@ -346,29 +323,24 @@ public String toString() { return getName().orElse(Identifier.of("??")) + "|" + getDataType() + "| ⇾ " + getUnderlying(); } - @Nonnull - public static Expression ofUnnamed(@Nonnull Value value) { + public static Expression ofUnnamed(Value value) { return ofUnnamed(DataTypeUtils.toRelationalType(value.getResultType()), value); } - @Nonnull - public static Expression of(@Nonnull Value value, @Nonnull Identifier identifier) { + public static Expression of(Value value, Identifier identifier) { return new Expression(Optional.of(identifier), DataTypeUtils.toRelationalType(value.getResultType()), value); } - @Nonnull - public static Expression ofUnnamed(@Nonnull DataType dataType, - @Nonnull Value expression) { + public static Expression ofUnnamed(DataType dataType, + Value expression) { return new Expression(Optional.empty(), dataType, expression); } - @Nonnull - public static Expression fromUnderlying(@Nonnull Value underlying) { + public static Expression fromUnderlying(Value underlying) { return new Expression(Optional.empty(), DataTypeUtils.toRelationalType(underlying.getResultType()), underlying); } - @Nonnull - public static Expression fromColumn(@Nonnull Column column) { + public static Expression fromColumn(Column column) { final var result = Expression.ofUnnamed(column.getValue()); if (column.getField().getFieldNameOptional().isPresent()) { return result.withName(Identifier.of(column.getField().getFieldName())); @@ -381,18 +353,15 @@ public static final class Utils { private Utils() { } - @Nonnull - public static Iterable filterUnderlyingAggregates(@Nonnull final Expression expression) { + public static Iterable filterUnderlyingAggregates(final Expression expression) { return filterUnderlying(expression, true); } - @Nonnull - public static Iterable filterUnderlyingNonAggregates(@Nonnull final Expression expression) { + public static Iterable filterUnderlyingNonAggregates(final Expression expression) { return filterUnderlying(expression, false); } - @Nonnull - private static Iterable filterUnderlying(@Nonnull final Expression expression, boolean onlyAggregates) { + private static Iterable filterUnderlying(final Expression expression, boolean onlyAggregates) { return Streams.stream(expression.getUnderlying().preOrderIterator(value -> value instanceof ArithmeticValue || value instanceof AndOrValue || @@ -412,9 +381,8 @@ private static Iterable filterUnderlying(@Nonnull final Expression expres * A literal ({@link LiteralValue}) folds to the corresponding {@link ConstantPredicate}. Everything * else is wrapped as a {@code ValuePredicate} performing a {@code «value» = TRUE} comparison. */ - @Nonnull - public static QueryPredicate toUnderlyingPredicate(@Nonnull final Expression expression, - @Nonnull final Set localAliases, + public static QueryPredicate toUnderlyingPredicate(final Expression expression, + final Set localAliases, boolean forDdl) { final Value value = expression.getUnderlying(); @@ -450,17 +418,15 @@ public static QueryPredicate toUnderlyingPredicate(@Nonnull final Expression exp } public static final class NamedArgumentExpression extends Expression { - private NamedArgumentExpression(@Nonnull Optional name, @Nonnull DataType dataType, @Nonnull Value expression, Visibility visibility) { + private NamedArgumentExpression(Optional name, DataType dataType, Value expression, Visibility visibility) { super(name, dataType, expression, visibility); } - @Nonnull @Override - protected Expression createNew(@Nonnull Optional newName, @Nonnull DataType newDataType, @Nonnull Value newUnderlying, @Nonnull Visibility newVisibility) { + protected Expression createNew(Optional newName, DataType newDataType, Value newUnderlying, Visibility newVisibility) { return new NamedArgumentExpression(newName, newDataType, newUnderlying, newVisibility); } - @Nonnull public Identifier getArgumentName() { return Assert.optionalUnchecked(getName()); } @@ -470,9 +436,8 @@ public boolean isNamedArgument() { return true; } - @Nonnull @Override - public NamedArgumentExpression toNamedArgument(@Nonnull final Identifier name) { + public NamedArgumentExpression toNamedArgument(final Identifier name) { if (name.equals(getArgumentName())) { return this; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Expressions.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Expressions.java index f0f7377556b..2c00803f6e2 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Expressions.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Expressions.java @@ -41,8 +41,6 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Streams; - -import javax.annotation.Nonnull; import java.util.Collection; import java.util.Collections; import java.util.Iterator; @@ -59,25 +57,21 @@ @API(API.Status.EXPERIMENTAL) public final class Expressions implements Iterable { - @Nonnull private static final Expressions EMPTY = new Expressions(ImmutableList.of()); - @Nonnull private final List underlying; private final Supplier> countsByNameSupplier = Suppliers.memoize(this::computeCountsByName); - private Expressions(@Nonnull Iterable underlying) { + private Expressions(Iterable underlying) { this.underlying = ImmutableList.copyOf(underlying); } - @Nonnull @Override public Iterator iterator() { return underlying.iterator(); } - @Nonnull public Expressions expanded() { return Expressions.of(underlying.stream() .flatMap(item -> item instanceof Star ? @@ -85,8 +79,7 @@ public Expressions expanded() { Stream.of(item)).collect(ImmutableList.toImmutableList())); } - @Nonnull - public Expressions rewireQov(@Nonnull Value value) { + public Expressions rewireQov(Value value) { final ImmutableList.Builder pulledUpOutputBuilder = ImmutableList.builder(); int colCount = 0; for (final var expression : this) { @@ -97,9 +90,8 @@ public Expressions rewireQov(@Nonnull Value value) { return Expressions.of(pulledUpOutputBuilder.build()); } - @Nonnull - public Expressions pullUp(@Nonnull Value value, @Nonnull CorrelationIdentifier correlationIdentifier, - @Nonnull Set constantAliases) { + public Expressions pullUp(Value value, CorrelationIdentifier correlationIdentifier, + Set constantAliases) { final AliasMap aliasMap = AliasMap.identitiesFor(value.getCorrelatedTo()); final Value simplifiedValue = value.simplify(EvaluationContext.empty(), aliasMap, constantAliases); return Expressions.of(stream() @@ -111,8 +103,7 @@ public Expressions pullUp(@Nonnull Value value, @Nonnull CorrelationIdentifier c .collect(ImmutableList.toImmutableList())); } - @Nonnull - public Expressions difference(@Nonnull Expressions that, @Nonnull final Set constantAliases) { + public Expressions difference(Expressions that, final Set constantAliases) { if (Iterables.isEmpty(that)) { return this; } @@ -136,33 +127,27 @@ public Expressions difference(@Nonnull Expressions that, @Nonnull final Set e.dereferenced(literals).stream()).collect(ImmutableList.toImmutableList())); } - @Nonnull public Expressions nonEphemeralVisible() { return Expressions.of(stream().filter(e -> !(e instanceof EphemeralExpression) && e.isVisible()).collect(ImmutableList.toImmutableList())); } - @Nonnull public Expression getSingleItem() { Assert.thatUnchecked(size() == 1, "invalid attempt to get single item"); return asList().get(0); } - @Nonnull public Set collectAggregateValues() { final ImmutableSet.Builder resultBuilder = ImmutableSet.builder(); for (final var expression : this) { @@ -171,19 +156,16 @@ public Set collectAggregateValues() { return resultBuilder.build(); } - @Nonnull - public Expressions replaceQualifier(@Nonnull Function, Collection> replaceFunc) { + public Expressions replaceQualifier(Function, Collection> replaceFunc) { return Expressions.of(underlying.stream().map(expression -> expression.replaceQualifier(replaceFunc)) .collect(ImmutableList.toImmutableList())); } - @Nonnull - public Expressions withQualifier(@Nonnull final Identifier qualifier) { + public Expressions withQualifier(final Identifier qualifier) { return Expressions.of(underlying.stream().map(expression -> expression.withQualifier(Optional.of(qualifier))) .collect(ImmutableList.toImmutableList())); } - @Nonnull public Expressions clearQualifier() { return Expressions.of(underlying.stream().map(Expression::clearQualifier).collect(ImmutableList.toImmutableList())); } @@ -204,12 +186,10 @@ private Map computeCountsByName() { return Collections.unmodifiableMap(countsByColumnName); } - @Nonnull public Iterable underlying() { return Streams.stream(this).map(Expression::getUnderlying).collect(ImmutableList.toImmutableList()); } - @Nonnull public List underlyingTypes() { return Streams.stream(underlying()).map(Value::getResultType).collect(ImmutableList.toImmutableList()); } @@ -233,7 +213,6 @@ public List underlyingTypes() { * * @return A StructType with field names and semantic types from expressions */ - @Nonnull public DataType.StructType getStructType() { final ImmutableList.Builder fieldsBuilder = ImmutableList.builder(); int index = 0; @@ -251,12 +230,10 @@ public DataType.StructType getStructType() { return DataType.StructType.from(generatedName, fieldsBuilder.build(), true); } - @Nonnull public Stream stream() { return underlying.stream(); } - @Nonnull public Collection> underlyingAsColumns() { Map countsByName = countsByNameSupplier.get(); return Streams.stream(this) @@ -278,18 +255,15 @@ public Collection> underlyingAsColumns() { .collect(ImmutableList.toImmutableList()); } - @Nonnull - public Iterable underlyingRebased(@Nonnull CorrelationIdentifier source, @Nonnull CorrelationIdentifier target) { + public Iterable underlyingRebased(CorrelationIdentifier source, CorrelationIdentifier target) { final var aliasMap = AliasMap.ofAliases(source, target); return Streams.stream(underlying()).map(value -> value.rebase(aliasMap)).collect(ImmutableList.toImmutableList()); } - @Nonnull public List asList() { return underlying; } - @Nonnull public Expressions asNamedArguments() { return Expressions.of(Streams.stream(this).map(Expression::toNamedArgument).collect(ImmutableList.toImmutableList())); } @@ -298,7 +272,6 @@ public boolean allNamedArguments() { return Streams.stream(this).allMatch(Expression::isNamedArgument); } - @Nonnull public List argumentNames() { Assert.thatUnchecked(allNamedArguments()); return Streams.stream(this).map(Expression::getName).flatMap(Optional::stream).map(Identifier::toString) @@ -309,7 +282,6 @@ public boolean noneNamedArguments() { return Streams.stream(this).noneMatch(Expression::isNamedArgument); } - @Nonnull public Map toNamedArgumentInvocation() { Assert.thatUnchecked(allNamedArguments()); final var resultBuilder = ImmutableMap.builder(); @@ -321,12 +293,10 @@ public Map toNamedArgumentInvocation() { return resultBuilder.build(); } - @Nonnull public CallSiteArguments toCallSiteArguments() { return toCallSiteArguments(false); } - @Nonnull public CallSiteArguments toCallSiteArguments(final boolean flattenSingleItemRecords) { if (isEmpty()) { return CallSiteArguments.empty(); @@ -348,34 +318,28 @@ public String toString() { return underlying.stream().map(Expression::toString).collect(Collectors.joining(",", "[", "]")); } - @Nonnull - public static Expressions of(@Nonnull Iterable expressions) { + public static Expressions of(Iterable expressions) { return new Expressions(expressions); } - @Nonnull - public static Expressions of(@Nonnull final Expression[] expressions) { + public static Expressions of(final Expression[] expressions) { List expressionsList = ImmutableList.copyOf(expressions); return Expressions.of(expressionsList); } - @Nonnull - public static Expressions ofSingle(@Nonnull Expression expression) { + public static Expressions ofSingle(Expression expression) { return new Expressions(ImmutableList.of(expression)); } - @Nonnull - public static Expressions fromQuantifier(@Nonnull Quantifier quantifier) { + public static Expressions fromQuantifier(Quantifier quantifier) { return Expressions.of(quantifier.getFlowedColumns().stream().map(Expression::fromColumn) .collect(ImmutableList.toImmutableList())); } - @Nonnull - public static Expressions fromUnderlying(@Nonnull Iterable values) { + public static Expressions fromUnderlying(Iterable values) { return Expressions.of(Streams.stream(values).map(Expression::fromUnderlying).collect(ImmutableList.toImmutableList())); } - @Nonnull public static Expressions empty() { return EMPTY; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/FieldValueTrieNode.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/FieldValueTrieNode.java index 05b54f6d992..88fbc3d6125 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/FieldValueTrieNode.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/FieldValueTrieNode.java @@ -34,9 +34,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterators; import com.google.common.collect.PeekingIterator; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.Collection; import java.util.List; import java.util.Map; @@ -49,7 +47,7 @@ @API(API.Status.EXPERIMENTAL) public class FieldValueTrieNode extends TrieNode.AbstractTrieNode { - public FieldValueTrieNode(@Nonnull final Value value, @Nullable final Map childrenMap) { + public FieldValueTrieNode(final Value value, @Nullable final Map childrenMap) { super(value, childrenMap); } @@ -57,7 +55,7 @@ public FieldValueTrieNode(@Nullable final Map semanticEqualsForChildrenMap(t, o, equivalencesMap)); } - private static boolean semanticEqualsForChildrenMap(@Nonnull final Map self, - @Nonnull final Map other, - @Nonnull final AliasMap equivalencesMap) { + private static boolean semanticEqualsForChildrenMap(final Map self, + final Map other, + final AliasMap equivalencesMap) { if (self.size() != other.size()) { return false; } @@ -118,7 +115,7 @@ private static boolean semanticEqualsForChildrenMap(@Nonnull final Map boolean equalsNullable(@Nullable final T self, @Nullable final T other, - @Nonnull final BiFunction nonNullableTest) { + final BiFunction nonNullableTest) { if (self == null && other == null) { return true; } @@ -133,7 +130,7 @@ public int hashCode() { return Objects.hash(getValue(), getChildrenMap()); } - public void validateNoOverlaps(@Nonnull Collection otherNodes) { + public void validateNoOverlaps(Collection otherNodes) { // Make sure the same field path isn't referenced by other nodes Map children = getChildrenMap(); if (children == null || children.isEmpty()) { @@ -164,15 +161,13 @@ public boolean isLeaf() { * * @return a trie representation of the ordered field paths. */ - @Nonnull - public static FieldValueTrieNode computeTrieForFieldPaths(@Nonnull final Collection orderedFieldPaths) { + public static FieldValueTrieNode computeTrieForFieldPaths(final Collection orderedFieldPaths) { return computeTrieForFieldPaths(new FieldValue.FieldPath(ImmutableList.of()), orderedFieldPaths, Iterators.peekingIterator(orderedFieldPaths.iterator())); } - @Nonnull - private static FieldValueTrieNode computeTrieForFieldPaths(@Nonnull final FieldValue.FieldPath prefix, - @Nonnull final Collection orderedFieldPaths, - @Nonnull final PeekingIterator orderedFieldPathIterator) { + private static FieldValueTrieNode computeTrieForFieldPaths(final FieldValue.FieldPath prefix, + final Collection orderedFieldPaths, + final PeekingIterator orderedFieldPathIterator) { if (orderedFieldPaths.contains(prefix)) { orderedFieldPathIterator.next(); return new FieldValueTrieNode(); @@ -198,9 +193,8 @@ private static FieldValueTrieNode computeTrieForFieldPaths(@Nonnull final FieldV return new FieldValueTrieNode(childrenMapBuilder.build()); } - @Nonnull - public static FieldValueTrieNode computeTrieForValues(@Nonnull final FieldValue.FieldPath prefix, - @Nonnull final PeekingIterator orderedValueIterator) { + public static FieldValueTrieNode computeTrieForValues(final FieldValue.FieldPath prefix, + final PeekingIterator orderedValueIterator) { final List prefixAccessors = prefix.getFieldAccessors(); final var childrenMapBuilder = ImmutableMap.builder(); while (orderedValueIterator.hasNext()) { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Identifier.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Identifier.java index 93a5ec43ed3..9db726b4bf2 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Identifier.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Identifier.java @@ -23,8 +23,6 @@ import com.apple.foundationdb.annotation.API; import com.google.common.collect.ImmutableList; - -import javax.annotation.Nonnull; import java.util.Collection; import java.util.List; import java.util.Objects; @@ -32,23 +30,19 @@ @API(API.Status.EXPERIMENTAL) public class Identifier { - @Nonnull private final String name; - @Nonnull private final List qualifier; - protected Identifier(@Nonnull String name, @Nonnull Iterable qualifier) { + protected Identifier(String name, Iterable qualifier) { this.name = name; this.qualifier = ImmutableList.copyOf(qualifier); } - @Nonnull public String getName() { return name; } - @Nonnull public List getQualifier() { return qualifier; } @@ -62,18 +56,15 @@ public String toString() { return String.join(".", qualifier) + (qualifier.isEmpty() ? "" : ".") + name; } - @Nonnull - public static Identifier of(@Nonnull String name) { + public static Identifier of(String name) { return new Identifier(name, ImmutableList.of()); } - @Nonnull - public static Identifier of(@Nonnull String name, @Nonnull Iterable qualifier) { + public static Identifier of(String name, Iterable qualifier) { return new Identifier(name, qualifier); } - @Nonnull - public Identifier withQualifier(@Nonnull Collection qualifier) { + public Identifier withQualifier(Collection qualifier) { if (qualifier.isEmpty()) { return this; } @@ -83,8 +74,7 @@ public Identifier withQualifier(@Nonnull Collection qualifier) { return new Identifier(name, newQualifierBuilder.build()); } - @Nonnull - public Identifier replaceQualifier(@Nonnull Function, Collection> replaceFunc) { + public Identifier replaceQualifier(Function, Collection> replaceFunc) { final var replacingQualifier = replaceFunc.apply(qualifier); if (replacingQualifier.equals(qualifier)) { return this; @@ -92,12 +82,10 @@ public Identifier replaceQualifier(@Nonnull Function, Collect return new Identifier(name, replacingQualifier); } - @Nonnull - public Identifier withQualifier(@Nonnull String qualifier) { + public Identifier withQualifier(String qualifier) { return withQualifier(List.of(qualifier)); } - @Nonnull public Identifier withoutQualifier() { if (!isQualified()) { return this; @@ -105,7 +93,6 @@ public Identifier withoutQualifier() { return new Identifier(getName(), ImmutableList.of()); } - @Nonnull public List fullyQualifiedName() { // todo: should amortize if (!isQualified()) { @@ -114,7 +101,7 @@ public List fullyQualifiedName() { return ImmutableList.builder().addAll(getQualifier()).add(name).build(); } - public boolean prefixedWith(@Nonnull Identifier identifier) { + public boolean prefixedWith(Identifier identifier) { final var identifierFullName = identifier.fullyQualifiedName(); final var fullName = fullyQualifiedName(); if (fullName.size() < identifierFullName.size()) { @@ -128,7 +115,7 @@ public boolean prefixedWith(@Nonnull Identifier identifier) { return true; } - public boolean qualifiedWith(@Nonnull Identifier identifier) { + public boolean qualifiedWith(Identifier identifier) { final var identifierFullName = identifier.fullyQualifiedName(); final var fullName = fullyQualifiedName(); if (fullName.size() != identifierFullName.size() + 1) { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Literals.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Literals.java index 64f39bf1d67..5eb664a25df 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Literals.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Literals.java @@ -32,9 +32,7 @@ import com.google.common.collect.Multiset; import com.google.common.collect.TreeMultiset; import com.google.protobuf.ByteString; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; @@ -48,16 +46,13 @@ public class Literals { - @Nonnull private static final Literals EMPTY = new Literals(ImmutableList.of()); - @Nonnull private final List orderedLiterals; - @Nonnull private final Supplier> asMapSupplier; - private Literals(@Nonnull final List orderedLiterals) { + private Literals(final List orderedLiterals) { this.orderedLiterals = ImmutableList.copyOf(orderedLiterals); // Using unmodifiableMap because it allows null values, which are valid here // and represent either null constants or null prepared parameters in queries. @@ -68,7 +63,6 @@ private Literals(@Nonnull final List orderedLiterals) { .collect(LinkedHashMap::new, (m, v) -> m.put(v.getConstantId(), v.getLiteralObject()), LinkedHashMap::putAll))); } - @Nonnull public List getOrderedLiterals() { return orderedLiterals; } @@ -81,12 +75,10 @@ public Map asMap() { return asMapSupplier.get(); } - @Nonnull public static Literals empty() { return EMPTY; } - @Nonnull public static Builder newBuilder() { return new Builder(); } @@ -94,16 +86,12 @@ public static Builder newBuilder() { @SuppressWarnings("OptionalUsedAsFieldOrParameterType") public static final class Builder { - @Nonnull private final Multiset literals; - @Nonnull private final Stack> current; - @Nonnull private final Map literalReverseLookup; // allowing null keys. - @Nonnull private Optional scope; private int arrayLiteralScopeCount; @@ -127,26 +115,25 @@ private void startComplexLiteral() { * @param scope the scope. * @return {@code this} builder. */ - @Nonnull - public Builder setScope(@Nonnull final String scope) { + public Builder setScope(final String scope) { this.scope = Optional.of(scope); return this; } - public List importLiteralsRetrieveNewLiterals(@Nonnull final Literals other) { + public List importLiteralsRetrieveNewLiterals(final Literals other) { return other.getOrderedLiterals().stream().filter(literal -> addLiteral(literal, false)) .collect(ImmutableList.toImmutableList()); } - public void importLiterals(@Nonnull final Literals other) { + public void importLiterals(final Literals other) { other.getOrderedLiterals().forEach(literalToImport -> addLiteral(literalToImport, false)); } - public void addLiteral(@Nonnull final OrderedLiteral orderedLiteral) { + public void addLiteral(final OrderedLiteral orderedLiteral) { addLiteral(orderedLiteral, true); } - private boolean addLiteral(@Nonnull final OrderedLiteral orderedLiteral, boolean verifyNotExists) { + private boolean addLiteral(final OrderedLiteral orderedLiteral, boolean verifyNotExists) { final var currentLiterals = current.peek(); if (orderedLiteral.getLiteralObject() instanceof byte[]) { // it is not clear why there is a special code path for array literal that avoids the @@ -175,8 +162,7 @@ private boolean addLiteral(@Nonnull final OrderedLiteral orderedLiteral, boolean return true; } - @Nonnull - public OrderedLiteral addLiteral(@Nonnull final Type type, @Nullable final Object literalObject, + public OrderedLiteral addLiteral(final Type type, @Nullable final Object literalObject, @Nullable final Integer unnamedParameterIndex, @Nullable final String parameterName, final int tokenIndex) { final var literal = new OrderedLiteral(type, literalObject, unnamedParameterIndex, parameterName, tokenIndex, scope); @@ -195,7 +181,6 @@ public void startStructLiteral() { } - @Nonnull public Optional getFirstValueDuplicateMaybe(@Nullable Object value) { // if this is called while building a complex literal, bail out, since we do not support // non-linear reference graphs at the moment. @@ -205,8 +190,7 @@ public Optional getFirstValueDuplicateMaybe(@Nullable Object val return Optional.of(literalReverseLookup.get(value)); } - @Nonnull - public Optional getFirstDuplicateOfConstantIdMaybe(@Nonnull String constantId) { + public Optional getFirstDuplicateOfConstantIdMaybe(String constantId) { // if this is called while building a complex literal, bail out, since we do not support // non-linear reference graphs at the moment. if (current.size() > 1) { @@ -246,7 +230,7 @@ public void finishArrayLiteral(@Nullable final Integer unnamedParameterIndex, arrayLiteralScopeCount--; } - public void finishStructLiteral(@Nonnull final Type.Record type, + public void finishStructLiteral(final Type.Record type, @Nullable final Integer unnamedParameterIndex, @Nullable final String parameterName, final int tokenIndex) { @@ -274,7 +258,7 @@ public void finishStructLiteral(@Nonnull final Type.Record type, structLiteralScopeCount--; } - private static Object transformFieldValue(@Nonnull Object fieldValue) { + private static Object transformFieldValue(Object fieldValue) { if (fieldValue instanceof UUID) { return TupleFieldsHelper.toProto((UUID) fieldValue); } @@ -289,12 +273,10 @@ public boolean isEmpty() { return literals.isEmpty(); } - @Nonnull public Literals build() { return new Literals(literals.stream().collect(ImmutableList.toImmutableList())); } - @Nonnull public String constructConstantId(int tokenIndex) { return "c" + scope.orElse("") + tokenIndex; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LiteralsUtils.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LiteralsUtils.java index de001d36fef..22fc4c8018d 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LiteralsUtils.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LiteralsUtils.java @@ -35,9 +35,7 @@ import com.google.protobuf.DynamicMessage; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.Message; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.List; import java.util.Objects; @@ -52,7 +50,6 @@ private LiteralsUtils() { // This is not sufficient, as we should try to coercion struct types rather than checking for them being // identical. https://github.com/FoundationDB/fdb-record-layer/issues/3472 - @Nonnull public static Type.Array resolveArrayTypeFromObjectsList(List objects) { DataType distinctType = null; for (var object: objects) { @@ -68,8 +65,7 @@ public static Type.Array resolveArrayTypeFromObjectsList(List objects) { return new Type.Array(distinctType == null ? Type.nullType() : DataTypeUtils.toRecordLayerType(distinctType)); } - @Nonnull - public static LiteralObject objectToLiteralObjectProto(@Nonnull final Type type, @Nullable final Object object) { + public static LiteralObject objectToLiteralObjectProto(final Type type, @Nullable final Object object) { final var builder = LiteralObject.newBuilder(); if (object == null) { return builder.build(); @@ -97,9 +93,9 @@ public static LiteralObject objectToLiteralObjectProto(@Nonnull final Type type, } @Nullable - public static Object objectFromLiteralObjectProto(@Nonnull final TypeRepository typeRepository, - @Nonnull final Type type, - @Nonnull final LiteralObject literalObject) { + public static Object objectFromLiteralObjectProto(final TypeRepository typeRepository, + final Type type, + final LiteralObject literalObject) { if (literalObject.hasScalarObject()) { return PlanSerialization.protoToValueObject(literalObject.getScalarObject()); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperator.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperator.java index 3546acb3a28..8cb08a2479f 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperator.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperator.java @@ -63,8 +63,6 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Sets; import com.google.common.collect.Streams; - -import javax.annotation.Nonnull; import java.util.Collection; import java.util.Iterator; import java.util.List; @@ -95,40 +93,33 @@ @API(API.Status.EXPERIMENTAL) public class LogicalOperator { - @Nonnull private final Optional name; - @Nonnull private final Expressions output; - @Nonnull private final Quantifier quantifier; - public LogicalOperator(@Nonnull Optional name, - @Nonnull Expressions output, - @Nonnull Quantifier quantifier) { + public LogicalOperator(Optional name, + Expressions output, + Quantifier quantifier) { this.name = name; this.output = output; this.quantifier = quantifier; } - @Nonnull public Optional getName() { return name; } - @Nonnull public Expressions getOutput() { return output; } - @Nonnull public Quantifier getQuantifier() { return quantifier; } - @Nonnull - public LogicalOperator withName(@Nonnull Identifier name) { + public LogicalOperator withName(Identifier name) { if (getName().isPresent() && getName().get().equals(name)) { return this; } @@ -149,40 +140,35 @@ public LogicalOperator withName(@Nonnull Identifier name) { }), getQuantifier()); } - @Nonnull - public LogicalOperator withAdditionalOutput(@Nonnull Expressions expressions) { + public LogicalOperator withAdditionalOutput(Expressions expressions) { return LogicalOperator.newOperatorWithPreservedExpressionNames(getName(), output.concat(expressions), getQuantifier()); } - @Nonnull - public LogicalOperator withOutput(@Nonnull Expressions expressions) { + public LogicalOperator withOutput(Expressions expressions) { return LogicalOperator.newOperatorWithPreservedExpressionNames(getName(), expressions, getQuantifier()); } - @Nonnull @SuppressWarnings("PMD.CompareObjectsWithEquals") - public LogicalOperator withQuantifier(@Nonnull Quantifier quantifier) { + public LogicalOperator withQuantifier(Quantifier quantifier) { if (quantifier == getQuantifier()) { return this; } return LogicalOperator.newOperator(getName(), getOutput(), quantifier); } - @Nonnull - public LogicalOperator withNewSharedReferenceAndAlias(@Nonnull Optional alias) { + public LogicalOperator withNewSharedReferenceAndAlias(Optional alias) { final var quantifier = Quantifier.forEach(getQuantifier().getRangesOver()); final var result = withOutput(getOutput().rewireQov(quantifier.getFlowedObjectValue())).withQuantifier(quantifier); return alias.map(result::withName).orElse(result); } - @Nonnull - public static LogicalOperator generateAccess(@Nonnull Identifier identifier, - @Nonnull Optional alias, - @Nonnull Optional atAlias, - @Nonnull Set requestedIndexes, - @Nonnull SemanticAnalyzer semanticAnalyzer, - @Nonnull LogicalPlanFragment currentPlanFragment, - @Nonnull LogicalOperatorCatalog logicalOperatorCatalog) { + public static LogicalOperator generateAccess(Identifier identifier, + Optional alias, + Optional atAlias, + Set requestedIndexes, + SemanticAnalyzer semanticAnalyzer, + LogicalPlanFragment currentPlanFragment, + LogicalOperatorCatalog logicalOperatorCatalog) { // look up any localized artifacts, such as common table expressions. final var cteMaybe = semanticAnalyzer.findCteMaybe(identifier, currentPlanFragment); if (cteMaybe.isPresent()) { @@ -226,44 +212,38 @@ public static LogicalOperator generateAccess(@Nonnull Identifier identifier, } } - @Nonnull - public static LogicalOperator newNamedOperator(@Nonnull Identifier name, - @Nonnull Expressions output, - @Nonnull Quantifier quantifier) { + public static LogicalOperator newNamedOperator(Identifier name, + Expressions output, + Quantifier quantifier) { return new LogicalOperator(Optional.of(name), output.withQualifier(name), quantifier); } - @Nonnull - public static LogicalOperator newUnnamedOperator(@Nonnull Expressions output, - @Nonnull Quantifier quantifier) { + public static LogicalOperator newUnnamedOperator(Expressions output, + Quantifier quantifier) { return new LogicalOperator(Optional.empty(), output.clearQualifier(), quantifier); } - @Nonnull - public static LogicalOperator newOperator(@Nonnull Optional name, - @Nonnull Expressions output, - @Nonnull Quantifier quantifier) { + public static LogicalOperator newOperator(Optional name, + Expressions output, + Quantifier quantifier) { return name.map(identifier -> newNamedOperator(identifier, output, quantifier)) .orElseGet(() -> newUnnamedOperator(output, quantifier)); } - @Nonnull - public static LogicalOperator newOperatorWithPreservedExpressionNames(@Nonnull Expressions output, - @Nonnull Quantifier quantifier) { + public static LogicalOperator newOperatorWithPreservedExpressionNames(Expressions output, + Quantifier quantifier) { return newOperatorWithPreservedExpressionNames(Optional.empty(), output, quantifier); } - @Nonnull - public static LogicalOperator newOperatorWithPreservedExpressionNames(@Nonnull Optional name, - @Nonnull Expressions output, - @Nonnull Quantifier quantifier) { + public static LogicalOperator newOperatorWithPreservedExpressionNames(Optional name, + Expressions output, + Quantifier quantifier) { return new LogicalOperator(name, output, quantifier); } - @Nonnull - public static LogicalOperator generateTableAccess(@Nonnull Identifier tableId, - @Nonnull Set indexAccessHints, - @Nonnull SemanticAnalyzer semanticAnalyzer) { + public static LogicalOperator generateTableAccess(Identifier tableId, + Set indexAccessHints, + SemanticAnalyzer semanticAnalyzer) { final Set tableNames = semanticAnalyzer.getAllTableStorageNames(); semanticAnalyzer.validateIndexes(tableId, indexAccessHints); final var scanExpression = Quantifier.forEach(Reference.initialOf( @@ -303,10 +283,9 @@ public static LogicalOperator generateTableAccess(@Nonnull Identifier tableId, return LogicalOperator.newNamedOperator(tableId, attributes, resultingQuantifier); } - @Nonnull - private static LogicalOperator generateCorrelatedFieldAccess(@Nonnull Expression expression, - @Nonnull Optional alias, - @Nonnull Optional atAlias) { + private static LogicalOperator generateCorrelatedFieldAccess(Expression expression, + Optional alias, + Optional atAlias) { Assert.thatUnchecked(expression.getDataType().getCode() == DataType.Code.ARRAY, ErrorCode.INVALID_COLUMN_REFERENCE, () -> String.format(Locale.ROOT, "join correlation can occur only on column of repeated type, not %s type", expression.getDataType())); @@ -355,8 +334,7 @@ private static LogicalOperator generateCorrelatedFieldAccess(@Nonnull Expression return operator; } - @Nonnull - public static Expressions convertToExpressions(@Nonnull Quantifier quantifier) { + public static Expressions convertToExpressions(Quantifier quantifier) { final ImmutableList.Builder attributesBuilder = ImmutableList.builder(); int colCount = 0; final var columns = quantifier.getFlowedColumns(); @@ -372,13 +350,12 @@ public static Expressions convertToExpressions(@Nonnull Quantifier quantifier) { return Expressions.of(attributesBuilder.build()); } - @Nonnull - public static LogicalOperator generateSelect(@Nonnull Expressions output, - @Nonnull LogicalOperators logicalOperators, - @Nonnull Optional predicate, - @Nonnull List orderBys, - @Nonnull Optional alias, - @Nonnull Set outerCorrelations, + public static LogicalOperator generateSelect(Expressions output, + LogicalOperators logicalOperators, + Optional predicate, + List orderBys, + Optional alias, + Set outerCorrelations, boolean isTopLevel, boolean isForDdl) { if (orderBys.isEmpty()) { @@ -401,10 +378,9 @@ public static LogicalOperator generateSelect(@Nonnull Expressions output, } } - @Nonnull - public static LogicalOperator generateSelectWhere(@Nonnull LogicalOperators logicalOperators, - @Nonnull Set outerCorrelations, - @Nonnull Optional where, + public static LogicalOperator generateSelectWhere(LogicalOperators logicalOperators, + Set outerCorrelations, + Optional where, boolean isForDdl) { final var quantifiers = logicalOperators.getQuantifiers(); final var quantifiedObjectValues = quantifiers.stream().map(QuantifiedObjectValue::of).collect(ImmutableList.toImmutableList()); @@ -420,14 +396,13 @@ public static LogicalOperator generateSelectWhere(@Nonnull LogicalOperators logi return LogicalOperator.newOperatorWithPreservedExpressionNames(output, resultingQuantifier); } - @Nonnull @SuppressWarnings("unchecked") - public static LogicalOperator generateGroupBy(@Nonnull LogicalOperators logicalOperators, - @Nonnull Expressions groupByExpressions, - @Nonnull Expressions outputExpressions, - @Nonnull Optional havingPredicate, - @Nonnull Set outerCorrelations, - @Nonnull Literals literals) { + public static LogicalOperator generateGroupBy(LogicalOperators logicalOperators, + Expressions groupByExpressions, + Expressions outputExpressions, + Optional havingPredicate, + Set outerCorrelations, + Literals literals) { final var aliasMap = AliasMap.identitiesFor(logicalOperators.getCorrelations()); final var aggregates = Expressions.of(havingPredicate.map(outputExpressions::concat).orElse(outputExpressions) .collectAggregateValues().stream().map(Expression::fromUnderlying).collect(ImmutableSet.toImmutableSet())); @@ -458,12 +433,11 @@ public static LogicalOperator generateGroupBy(@Nonnull LogicalOperators logicalO return LogicalOperator.newUnnamedOperator(output, resultingQuantifier); } - @Nonnull - public static LogicalOperator generateSimpleSelect(@Nonnull Expressions output, - @Nonnull LogicalOperators logicalOperators, - @Nonnull Optional where, - @Nonnull Optional alias, - @Nonnull Set outerCorrelations, + public static LogicalOperator generateSimpleSelect(Expressions output, + LogicalOperators logicalOperators, + Optional where, + Optional alias, + Set outerCorrelations, boolean isForDdl) { final var quantifiers = logicalOperators.getQuantifiers(); final var selectBuilder = GraphExpansion.builder().addAllQuantifiers(quantifiers); @@ -501,8 +475,8 @@ public static LogicalOperator generateSimpleSelect(@Nonnull Expressions output, * @return {@code true} if projecting individual columns of the underlying quantifier can be avoided, otherwise * {@code false}. */ - private static boolean canAvoidProjectingIndividualFields(@Nonnull Expressions output, - @Nonnull LogicalOperators logicalOperators) { + private static boolean canAvoidProjectingIndividualFields(Expressions output, + LogicalOperators logicalOperators) { // No joins if (Iterables.size(logicalOperators.forEachOnly()) != 1 || Iterables.size(output) != 1) { return false; @@ -549,11 +523,10 @@ private static boolean canAvoidProjectingIndividualFields(@Nonnull Expressions o return true; } - @Nonnull - public static LogicalOperator generateSort(@Nonnull LogicalOperator logicalOperator, - @Nonnull List orderBys, - @Nonnull Set outerCorrelations, - @Nonnull Optional alias) { + public static LogicalOperator generateSort(LogicalOperator logicalOperator, + List orderBys, + Set outerCorrelations, + Optional alias) { final LogicalSortExpression sortExpression; if (orderBys.isEmpty()) { sortExpression = LogicalSortExpression.unsorted(logicalOperator.quantifier); @@ -578,8 +551,7 @@ public static LogicalOperator generateSort(@Nonnull LogicalOperator logicalOpera return LogicalOperator.newOperator(alias, resultingExpressions, resultingQuantifier); } - @Nonnull - public static LogicalOperator generateInsert(@Nonnull LogicalOperator insertSource, @Nonnull Table target) { + public static LogicalOperator generateInsert(LogicalOperator insertSource, Table target) { final Type.Record targetType = Assert.castUnchecked(target, RecordLayerTable.class).getType(); final var insertExpression = new InsertExpression(Assert.castUnchecked(insertSource.getQuantifier(), Quantifier.ForEach.class), @@ -591,8 +563,7 @@ public static LogicalOperator generateInsert(@Nonnull LogicalOperator insertSour return generateSort(insertOperator, List.of(), Set.of(), Optional.empty()); } - @Nonnull - public static CorrelationIdentifier getInnermostAlias(@Nonnull Iterable logicalOperators) { + public static CorrelationIdentifier getInnermostAlias(Iterable logicalOperators) { final Collection aliases = Streams.stream(logicalOperators) .map(LogicalOperator::getQuantifier) .filter(qun -> qun instanceof Quantifier.ForEach) @@ -601,9 +572,8 @@ public static CorrelationIdentifier getInnermostAlias(@Nonnull Iterable outerCorrelations) { + public static LogicalOperator generateUnionAll(LogicalOperators unionLegs, + Set outerCorrelations) { Assert.thatUnchecked(!unionLegs.isEmpty()); if (unionLegs.size() == 1) { return unionLegs.first(); @@ -647,8 +617,7 @@ public static LogicalOperator generateUnionAll(@Nonnull LogicalOperators unionLe return LogicalOperator.newUnnamedOperator(output, union); } - @Nonnull - public static Expressions adjustCountOnEmpty(@Nonnull final Expressions expressions) { + public static Expressions adjustCountOnEmpty(final Expressions expressions) { return Expressions.of(expressions.expanded().stream().map(expression -> { final var underlyingValue = expression.getUnderlying(); final Set visited = Sets.newIdentityHashSet(); @@ -667,10 +636,9 @@ public static Expressions adjustCountOnEmpty(@Nonnull final Expressions expressi }).collect(ImmutableList.toImmutableList())); } - @Nonnull - public static LogicalOperator newTemporaryTableScan(@Nonnull final Identifier operatorId, - @Nonnull final Identifier tempTableId, - @Nonnull final Type type) { + public static LogicalOperator newTemporaryTableScan(final Identifier operatorId, + final Identifier tempTableId, + final Type type) { final var tempTableAlias = CorrelationIdentifier.of(tempTableId.getName()); final var tempTableScan = TempTableScanExpression.ofCorrelated(tempTableAlias, type); final var quantifier = Quantifier.forEach(Reference.initialOf(tempTableScan)); @@ -678,10 +646,9 @@ public static LogicalOperator newTemporaryTableScan(@Nonnull final Identifier op return LogicalOperator.newNamedOperator(operatorId, expressions, quantifier); } - @Nonnull - public static LogicalOperator newTemporaryTableInsert(@Nonnull final LogicalOperator input, - @Nonnull final Identifier identifier, - @Nonnull final Type type) { + public static LogicalOperator newTemporaryTableInsert(final LogicalOperator input, + final Identifier identifier, + final Type type) { final var tempTableAlias = CorrelationIdentifier.of(identifier.getName()); final var tempTableInsert = TempTableInsertExpression.ofCorrelated(input.getQuantifier().narrow(Quantifier.ForEach.class), tempTableAlias, type); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperatorCatalog.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperatorCatalog.java index fd6275a7707..fdc9e4a4d4b 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperatorCatalog.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperatorCatalog.java @@ -23,8 +23,6 @@ import com.apple.foundationdb.annotation.API; import com.google.common.collect.ImmutableSet; - -import javax.annotation.Nonnull; import java.util.LinkedHashMap; import java.util.Map; import java.util.Optional; @@ -35,35 +33,30 @@ @API(API.Status.EXPERIMENTAL) public final class LogicalOperatorCatalog { - @Nonnull private final Map logicalOperators; private LogicalOperatorCatalog() { this.logicalOperators = new LinkedHashMap<>(); } - @Nonnull - public LogicalOperator lookup(@Nonnull CatalogKey key, @Nonnull Function mappingFunction) { + public LogicalOperator lookup(CatalogKey key, Function mappingFunction) { return logicalOperators.computeIfAbsent(key, mappingFunction); } - @Nonnull - public LogicalOperator lookupTableAccess(@Nonnull Identifier tableId, @Nonnull SemanticAnalyzer semanticAnalyzer) { + public LogicalOperator lookupTableAccess(Identifier tableId, SemanticAnalyzer semanticAnalyzer) { return lookupTableAccess(tableId, Optional.empty(), ImmutableSet.of(), semanticAnalyzer); } - @Nonnull - public LogicalOperator lookupTableAccess(@Nonnull Identifier tableId, - @Nonnull Optional alias, - @Nonnull Set requestedIndexes, - @Nonnull SemanticAnalyzer semanticAnalyzer) { + public LogicalOperator lookupTableAccess(Identifier tableId, + Optional alias, + Set requestedIndexes, + SemanticAnalyzer semanticAnalyzer) { return lookupTableAccess(CatalogKey.of(tableId, requestedIndexes), alias, semanticAnalyzer); } - @Nonnull - public LogicalOperator lookupTableAccess(@Nonnull CatalogKey key, - @Nonnull Optional alias, - @Nonnull SemanticAnalyzer semanticAnalyzer) { + public LogicalOperator lookupTableAccess(CatalogKey key, + Optional alias, + SemanticAnalyzer semanticAnalyzer) { if (!logicalOperators.containsKey(key)) { final var value = LogicalOperator.generateTableAccess(key.getIdentifier(), key.getHints(), semanticAnalyzer); logicalOperators.put(key, value); @@ -72,7 +65,6 @@ public LogicalOperator lookupTableAccess(@Nonnull CatalogKey key, return logicalOperators.get(key).withNewSharedReferenceAndAlias(alias); } - @Nonnull public static LogicalOperatorCatalog newInstance() { return new LogicalOperatorCatalog(); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperators.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperators.java index 661c8cfe874..b255039f82e 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperators.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperators.java @@ -29,8 +29,6 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; - -import javax.annotation.Nonnull; import java.util.Iterator; import java.util.List; import java.util.Set; @@ -39,33 +37,27 @@ @API(API.Status.EXPERIMENTAL) public class LogicalOperators implements Iterable { - @Nonnull private static final LogicalOperators EMPTY = new LogicalOperators(ImmutableList.of()); - @Nonnull private final List underlying; - public LogicalOperators(@Nonnull Iterable underlying) { + public LogicalOperators(Iterable underlying) { this.underlying = ImmutableList.copyOf(underlying); } - @Nonnull @Override public Iterator iterator() { return underlying.iterator(); } - @Nonnull public Stream stream() { return underlying.stream(); } - @Nonnull public List asList() { return underlying; } - @Nonnull public LogicalOperator first() { Assert.thatUnchecked(!underlying.isEmpty()); return underlying.get(0); @@ -79,17 +71,14 @@ public int size() { return underlying.size(); } - @Nonnull public Set getCorrelations() { return underlying.stream().map(operator -> operator.getQuantifier().getAlias()).collect(ImmutableSet.toImmutableSet()); } - @Nonnull public List getQuantifiers() { return underlying.stream().map(LogicalOperator::getQuantifier).collect(ImmutableList.toImmutableList()); } - @Nonnull public Expressions getExpressions() { Expressions accumulated = Expressions.empty(); for (final var logicalOperator : this) { @@ -98,34 +87,28 @@ public Expressions getExpressions() { return accumulated; } - @Nonnull public LogicalOperators forEachOnly() { return LogicalOperators.of(this.stream() .filter(operator -> operator.getQuantifier().getClass().equals(Quantifier.ForEach.class)) .collect(ImmutableList.toImmutableList())); } - @Nonnull - public LogicalOperators concat(@Nonnull LogicalOperator logicalOperator) { + public LogicalOperators concat(LogicalOperator logicalOperator) { return concat(LogicalOperators.ofSingle(logicalOperator)); } - @Nonnull - public LogicalOperators concat(@Nonnull LogicalOperators other) { + public LogicalOperators concat(LogicalOperators other) { return new LogicalOperators(Iterables.concat(this, other)); } - @Nonnull - public static LogicalOperators of(@Nonnull Iterable logicalOperators) { + public static LogicalOperators of(Iterable logicalOperators) { return new LogicalOperators(logicalOperators); } - @Nonnull - public static LogicalOperators ofSingle(@Nonnull LogicalOperator logicalOperator) { + public static LogicalOperators ofSingle(LogicalOperator logicalOperator) { return new LogicalOperators(ImmutableList.of(logicalOperator)); } - @Nonnull public static LogicalOperators empty() { return EMPTY; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalPlanFragment.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalPlanFragment.java index fa2450fafb8..42173d9df03 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalPlanFragment.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalPlanFragment.java @@ -26,9 +26,7 @@ import com.apple.foundationdb.relational.util.Assert; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -53,28 +51,24 @@ @API(API.Status.EXPERIMENTAL) public final class LogicalPlanFragment { - @Nonnull private final Optional parent; - @Nonnull private LogicalOperators operators; - @Nonnull private Optional state; - @Nonnull private final List innerJoinExpressions; - private LogicalPlanFragment(@Nonnull Optional parent, - @Nonnull LogicalOperators operators, - @Nonnull Optional state) { + private LogicalPlanFragment(Optional parent, + LogicalOperators operators, + Optional state) { this.parent = parent; this.operators = operators; this.state = state; this.innerJoinExpressions = new ArrayList<>(); } - public void addInnerJoinExpression(@Nonnull Expression joinExpression) { + public void addInnerJoinExpression(Expression joinExpression) { this.innerJoinExpressions.add(joinExpression); } @@ -82,17 +76,14 @@ public void clearInnerJoinExpressions() { this.innerJoinExpressions.clear(); } - @Nonnull public List getInnerJoinExpressions() { return Collections.unmodifiableList(innerJoinExpressions); } - @Nonnull public LogicalOperators getLogicalOperators() { return operators; } - @Nonnull public Optional getParentMaybe() { return parent; } @@ -101,13 +92,11 @@ public boolean hasParent() { return parent.isPresent(); } - @Nonnull public LogicalPlanFragment getParent() { Assert.thatUnchecked(parent.isPresent()); return parent.get(); } - @Nonnull public LogicalOperators getLogicalOperatorsIncludingOuter() { final ImmutableList.Builder resultBuilder = ImmutableList.builder(); resultBuilder.addAll(getLogicalOperators()); @@ -119,34 +108,31 @@ public LogicalOperators getLogicalOperatorsIncludingOuter() { return LogicalOperators.of(resultBuilder.build()); } - public void addOperator(@Nonnull LogicalOperator logicalOperator) { + public void addOperator(LogicalOperator logicalOperator) { this.operators = operators.concat(logicalOperator); } - public void setOperator(@Nonnull LogicalOperator logicalOperator) { + public void setOperator(LogicalOperator logicalOperator) { this.operators = LogicalOperators.ofSingle(logicalOperator); } - public void setState(@Nonnull State state) { + public void setState(State state) { this.state = Optional.of(state); } - public void setStateMaybe(@Nonnull Optional state) { + public void setStateMaybe(Optional state) { this.state = state; } - @Nonnull public State getState() { Assert.thatUnchecked(state.isPresent()); return state.get(); } - @Nonnull public Optional getStateMaybe() { return state; } - @Nonnull public Set getOuterCorrelations() { final ImmutableSet.Builder resultBuilder = ImmutableSet.builder(); var current = parent; @@ -157,46 +143,38 @@ public Set getOuterCorrelations() { return resultBuilder.build(); } - @Nonnull public LogicalPlanFragment addChild() { return LogicalPlanFragment.ofParent(Optional.of(this)); } - @Nonnull - private static LogicalPlanFragment ofParent(@Nonnull Optional parent) { + private static LogicalPlanFragment ofParent(Optional parent) { return new LogicalPlanFragment(parent, LogicalOperators.empty(), Optional.empty()); } - @Nonnull public static LogicalPlanFragment ofRoot() { return new LogicalPlanFragment(Optional.empty(), LogicalOperators.empty(), Optional.empty()); } public static final class State { - @Nonnull private final Optional targetType; - @Nonnull private final Optional targetTypeReorderings; - private State(@Nonnull Optional targetType, - @Nonnull Optional targetTypeReorderings) { + private State(Optional targetType, + Optional targetTypeReorderings) { this.targetType = targetType; this.targetTypeReorderings = targetTypeReorderings; } - @Nonnull public static Builder newBuilder() { return new Builder(); } - @Nonnull public Optional getTargetType() { return targetType; } - @Nonnull public Optional getTargetTypeReorderings() { return targetTypeReorderings; } @@ -212,19 +190,16 @@ public static final class Builder { private Builder() { } - @Nonnull - public Builder withTargetType(@Nonnull Type targetType) { + public Builder withTargetType(Type targetType) { this.targetType = targetType; return this; } - @Nonnull - public Builder withTargetTypeReorderings(@Nonnull StringTrieNode targetTypeReorderings) { + public Builder withTargetTypeReorderings(StringTrieNode targetTypeReorderings) { this.targetTypeReorderings = targetTypeReorderings; return this; } - @Nonnull public State build() { return new State(Optional.ofNullable(targetType), Optional.ofNullable(targetTypeReorderings)); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalQuery.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalQuery.java index 7f641c8ff0c..b4e825513d7 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalQuery.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalQuery.java @@ -23,8 +23,6 @@ import com.apple.foundationdb.annotation.API; import com.apple.foundationdb.record.query.plan.cascades.expressions.RelationalExpression; - -import javax.annotation.Nonnull; import java.util.Objects; /** @@ -42,12 +40,12 @@ public class LogicalQuery { // private final Set queryLiterals; - public LogicalQuery(@Nonnull String query, long queryHash) { + public LogicalQuery(String query, long queryHash) { this.query = query; this.queryHash = queryHash; } - public static LogicalQuery of(@Nonnull String query, @Nonnull RelationalExpression relExp) { + public static LogicalQuery of(String query, RelationalExpression relExp) { return new LogicalQuery(query, relExp.semanticHashCode()); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/MutablePlanGenerationContext.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/MutablePlanGenerationContext.java index 44e44d7779b..77f5acecfb9 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/MutablePlanGenerationContext.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/MutablePlanGenerationContext.java @@ -47,10 +47,7 @@ import com.google.common.collect.ImmutableList; import com.google.protobuf.ZeroCopyByteString; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.sql.Array; +import org.jspecify.annotations.Nullable; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Struct; @@ -60,6 +57,8 @@ import java.util.Optional; import java.util.function.Supplier; +import static com.apple.foundationdb.record.query.plan.cascades.typing.Type.Array; +import static com.apple.foundationdb.record.query.plan.cascades.typing.Type.Record; import static com.apple.foundationdb.relational.api.exceptions.ErrorCode.DATATYPE_MISMATCH; /** @@ -68,24 +67,18 @@ */ @API(API.Status.EXPERIMENTAL) public class MutablePlanGenerationContext implements QueryExecutionContext { - @Nonnull private final PreparedParams preparedParams; - @Nonnull private final Literals.Builder literalsBuilder; private final int parameterHash; - @Nonnull private final PlanHashable.PlanHashMode planHashMode; - @Nonnull private final String query; - @Nonnull private final String canonicalQueryString; - @Nonnull private final List constantObjectValues; private boolean shouldProcessLiteral; @@ -95,21 +88,20 @@ public class MutablePlanGenerationContext implements QueryExecutionContext { @Nullable private byte[] continuation; - @Nonnull private final ImmutableList.Builder equalityConstraints; private void startStructLiteral() { literalsBuilder.startStructLiteral(); } - private void finishStructLiteral(@Nonnull Type.Record type, + private void finishStructLiteral(Record type, @Nullable Integer unnamedParameterIndex, @Nullable String parameterName, int tokenIndex) { literalsBuilder.finishStructLiteral(type, unnamedParameterIndex, parameterName, tokenIndex); } - private void addLiteralReference(@Nonnull ConstantObjectValue constantObjectValue) { + private void addLiteralReference(ConstantObjectValue constantObjectValue) { if (!literalsBuilder.isAddingComplexLiteral()) { constantObjectValues.add(constantObjectValue); } @@ -138,9 +130,8 @@ private void addLiteralReference(@Nonnull ConstantObjectValue constantObjectValu * @return An {@link Optional} containing the corresponding {@link OrderedLiteral} if the literal was previously * encountered; otherwise, an empty {@link Optional}. */ - @Nonnull private Optional getFirstDuplicate(@Nullable Object literal, int requestedTokenIndex, - @Nonnull Type type) { + Type type) { final var orderedLiteralMaybe = literalsBuilder.getFirstValueDuplicateMaybe(literal); if (orderedLiteralMaybe.isEmpty()) { return Optional.empty(); @@ -150,8 +141,7 @@ private Optional getFirstDuplicate(@Nullable Object literal, int return orderedLiteralMaybe; } - @Nonnull - private Optional getFirstDuplicate(@Nonnull final String constantId) { + private Optional getFirstDuplicate(final String constantId) { final var firstDuplicateMaybe = literalsBuilder.getFirstDuplicateOfConstantIdMaybe(constantId); if (firstDuplicateMaybe.isEmpty()) { return firstDuplicateMaybe; @@ -161,7 +151,7 @@ private Optional getFirstDuplicate(@Nonnull final String constan return firstDuplicateMaybe; } - private void addEqualityConstraint(@Nonnull String leftTokenId, @Nonnull String rightTokenId, @Nonnull Type type) { + private void addEqualityConstraint(String leftTokenId, String rightTokenId, Type type) { if (leftTokenId.equals(rightTokenId)) { return; } @@ -192,18 +182,17 @@ private void setShouldProcessLiteral(boolean shouldProcessLiteral) { this.shouldProcessLiteral = shouldProcessLiteral; } - @Nonnull - private ConstantObjectValue processPreparedStatementArrayParameter(@Nonnull Array param, - @Nullable Type.Array type, + private ConstantObjectValue processPreparedStatementArrayParameter(java.sql.Array param, + @Nullable Array type, @Nullable Integer unnamedParameterIndex, @Nullable String parameterName, final int tokenIndex) { - Type.Array resolvedType = type; + Array resolvedType = type; startArrayLiteral(); final var arrayElements = new ArrayList<>(); try { if (type == null) { - resolvedType = (Type.Array) DataTypeUtils.toRecordLayerType(((RelationalArray) param).getMetaData().asRelationalType()); + resolvedType = (Array) DataTypeUtils.toRecordLayerType(((RelationalArray) param).getMetaData().asRelationalType()); } try (ResultSet rs = param.getResultSet()) { while (rs.next()) { @@ -225,8 +214,7 @@ private ConstantObjectValue processPreparedStatementArrayParameter(@Nonnull Arra return processComplexLiteral(tokenIndex, resolvedType); } - @Nonnull - private Value processQueryLiteralOrParameter(@Nonnull Type type, + private Value processQueryLiteralOrParameter(Type type, @Nullable Object literal, @Nullable Integer unnamedParameterIndex, @Nullable String parameterName, @@ -246,18 +234,17 @@ private Value processQueryLiteralOrParameter(@Nonnull Type type, } } - @Nonnull private Value processPreparedStatementParameter(@Nullable Object param, - @Nonnull Type type, + Type type, @Nullable Integer unnamedParameterIndex, @Nullable String parameterName, int tokenIndex) { - if (param instanceof Array) { + if (param instanceof java.sql.Array) { Assert.thatUnchecked(type.isArray(), DATATYPE_MISMATCH, "Array type field required as prepared statement parameter instead of " + type); - return processPreparedStatementArrayParameter((Array)param, (Type.Array)type, unnamedParameterIndex, parameterName, tokenIndex); + return processPreparedStatementArrayParameter((java.sql.Array)param, (Array)type, unnamedParameterIndex, parameterName, tokenIndex); } else if (param instanceof Struct) { Assert.thatUnchecked(type.isRecord(), DATATYPE_MISMATCH, "Required type field required as prepared statement parameter instead of " + type); - return processPreparedStatementStructParameter((Struct)param, (Type.Record)type, unnamedParameterIndex, parameterName, tokenIndex); + return processPreparedStatementStructParameter((Struct)param, (Record)type, unnamedParameterIndex, parameterName, tokenIndex); } else if (param instanceof byte[]) { return processQueryLiteralOrParameter(Type.primitiveType(Type.TypeCode.BYTES), ZeroCopyByteString.wrap((byte[])param), unnamedParameterIndex, parameterName, tokenIndex); @@ -266,10 +253,10 @@ private Value processPreparedStatementParameter(@Nullable Object param, } } - public MutablePlanGenerationContext(@Nonnull PreparedParams preparedParams, - @Nonnull PlanHashable.PlanHashMode planHashMode, - @Nonnull String query, - @Nonnull String canonicalQueryString, + public MutablePlanGenerationContext(PreparedParams preparedParams, + PlanHashable.PlanHashMode planHashMode, + String query, + String canonicalQueryString, int parameterHash) { this.preparedParams = preparedParams; this.planHashMode = planHashMode; @@ -284,7 +271,6 @@ public MutablePlanGenerationContext(@Nonnull PreparedParams preparedParams, equalityConstraints = ImmutableList.builder(); } - @Nonnull public PreparedParams getPreparedParams() { return preparedParams; } @@ -299,30 +285,25 @@ public void finishArrayLiteral(@Nullable Integer unnamedParameterIndex, literalsBuilder.finishArrayLiteral(unnamedParameterIndex, parameterName, shouldProcessLiteral, tokenIndex); } - @Nonnull @Override public Literals getLiterals() { // todo: this should be more efficient, we just need an immutable view over the elements of the builder. return literalsBuilder.build(); } - @Nonnull public Literals.Builder getLiteralsBuilder() { return literalsBuilder; } - @Nonnull @Override public PlanHashable.PlanHashMode getPlanHashMode() { return planHashMode; } - @Nonnull public String getQuery() { return query; } - @Nonnull public String getCanonicalQueryString() { return canonicalQueryString; } @@ -332,7 +313,6 @@ public boolean isForDdl() { return !shouldProcessLiteral; } - @Nonnull @Override public ExecuteProperties.Builder getExecutionPropertiesBuilder() { return ExecuteProperties.newBuilder(); @@ -356,7 +336,6 @@ public boolean isForExplain() { } - @Nonnull public QueryPlanConstraint getPlanConstraintsForLiteralReferences() { final ImmutableList.Builder predicateBuilder = ImmutableList.builder(); @@ -391,8 +370,7 @@ public void setForExplain(boolean forExplain) { this.forExplain = forExplain; } - @Nonnull - public Value processQueryLiteral(@Nonnull Type type, @Nullable Object literal, int tokenIndex) { + public Value processQueryLiteral(Type type, @Nullable Object literal, int tokenIndex) { return processQueryLiteralOrParameter(type, literal, null, null, tokenIndex); } @@ -406,8 +384,7 @@ public Value processQueryLiteral(@Nonnull Type type, @Nullable Object literal, i * * @return The result of the closure */ - @Nonnull - public T withDisabledLiteralProcessing(@Nonnull Supplier supplier) { + public T withDisabledLiteralProcessing(Supplier supplier) { boolean oldShouldProcessLiteral = shouldProcessLiteral(); setShouldProcessLiteral(false); final T result = supplier.get(); @@ -415,8 +392,7 @@ public T withDisabledLiteralProcessing(@Nonnull Supplier supplier) { return result; } - @Nonnull - public ConstantObjectValue processComplexLiteral(int tokenIndex, @Nonnull Type type) { + public ConstantObjectValue processComplexLiteral(int tokenIndex, Type type) { final var constantId = literalsBuilder.constructConstantId(tokenIndex); final var result = ConstantObjectValue.of(Quantifier.constant(), constantId, type); if (shouldProcessLiteral()) { @@ -426,18 +402,17 @@ public ConstantObjectValue processComplexLiteral(int tokenIndex, @Nonnull Type t getFirstDuplicate(constantId).map(OrderedLiteral::getConstantId).orElse(constantId), type); } - @Nonnull - public Value processPreparedStatementStructParameter(@Nonnull Struct param, - @Nullable Type.Record type, + public Value processPreparedStatementStructParameter(Struct param, + @Nullable Record type, @Nullable Integer unnamedParameterIndex, @Nullable String parameterName, int tokenIndex) { - Type.Record resolvedType = type; + Record resolvedType = type; startStructLiteral(); Object[] attributes; try { if (type == null) { - resolvedType = (Type.Record) DataTypeUtils.toRecordLayerType(((RelationalStruct) param).getMetaData().getRelationalDataType()); + resolvedType = (Record) DataTypeUtils.toRecordLayerType(((RelationalStruct) param).getMetaData().getRelationalDataType()); } attributes = param.getAttributes(); } catch (SQLException e) { @@ -452,7 +427,7 @@ public Value processPreparedStatementStructParameter(@Nonnull Struct param, return processComplexLiteral(tokenIndex, resolvedType); } - public void importAuxiliaryLiterals(@Nonnull final Literals auxiliaryLiterals) { + public void importAuxiliaryLiterals(final Literals auxiliaryLiterals) { final var newLiterals = literalsBuilder.importLiteralsRetrieveNewLiterals(auxiliaryLiterals); for (final var literal : newLiterals) { final var literalValue = new LiteralValue<>(literal.getLiteralObject()); @@ -462,14 +437,12 @@ public void importAuxiliaryLiterals(@Nonnull final Literals auxiliaryLiterals) { } } - @Nonnull - public Value processNamedPreparedParam(@Nonnull String param, int tokenIndex) { + public Value processNamedPreparedParam(String param, int tokenIndex) { final var value = preparedParams.namedParamValue(param); //TODO type should probably be Type.any() instead of null return processPreparedStatementParameter(value, getObjectType(value), null, param, tokenIndex); } - @Nonnull public Value processUnnamedPreparedParam(int tokenIndex) { // TODO (Make prepared statement parameters stateless) final int currentUnnamedParameterIndex = preparedParams.currentUnnamedParamIndex(); @@ -482,7 +455,6 @@ public Value processUnnamedPreparedParam(int tokenIndex) { return processPreparedStatementParameter(param, getObjectType(param), currentUnnamedParameterIndex, null, tokenIndex); } - @Nonnull private static Type getObjectType(@Nullable final Object object) { if (object instanceof WithMetadata) { try { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/NormalizedQueryExecutionContext.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/NormalizedQueryExecutionContext.java index 5b950dd4368..c6135d23994 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/NormalizedQueryExecutionContext.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/NormalizedQueryExecutionContext.java @@ -23,20 +23,18 @@ import com.apple.foundationdb.annotation.API; import com.apple.foundationdb.record.ExecuteProperties; -import com.apple.foundationdb.record.PlanHashable; import com.apple.foundationdb.relational.util.SpotBugsSuppressWarnings; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.Objects; +import static com.apple.foundationdb.record.PlanHashable.PlanHashMode; + /** * This context is populated during query normalization. It contains all the information required to execute a cached physical query plan. */ @API(API.Status.EXPERIMENTAL) public final class NormalizedQueryExecutionContext implements QueryExecutionContext { - @Nonnull private final Literals literals; @Nullable @@ -46,14 +44,13 @@ public final class NormalizedQueryExecutionContext implements QueryExecutionCont private final int parameterHash; - @Nonnull - private final PlanHashable.PlanHashMode planHashMode; + private final PlanHashMode planHashMode; - private NormalizedQueryExecutionContext(@Nonnull Literals literals, + private NormalizedQueryExecutionContext(Literals literals, @Nullable byte[] continuation, int parameterHash, boolean isForExplain, - @Nonnull final PlanHashable.PlanHashMode planHashMode) { + final PlanHashMode planHashMode) { this.literals = literals; this.continuation = continuation; this.isForExplain = isForExplain; @@ -61,13 +58,11 @@ private NormalizedQueryExecutionContext(@Nonnull Literals literals, this.planHashMode = planHashMode; } - @Nonnull @Override public Literals getLiterals() { return literals; } - @Nonnull @Override public ExecuteProperties.Builder getExecutionPropertiesBuilder() { return ExecuteProperties.newBuilder(); @@ -90,19 +85,16 @@ public boolean isForExplain() { return isForExplain; } - @Nonnull @Override - public PlanHashable.PlanHashMode getPlanHashMode() { + public PlanHashMode getPlanHashMode() { return planHashMode; } - @Nonnull public static Builder newBuilder() { return new Builder(); } public static final class Builder { - @Nonnull private final Literals.Builder literalsBuilder; private boolean isForExplain; @@ -113,7 +105,7 @@ public static final class Builder { private int parameterHash; @Nullable - private PlanHashable.PlanHashMode planHashMode; + private PlanHashMode planHashMode; private Builder() { this.literalsBuilder = Literals.newBuilder(); @@ -122,37 +114,31 @@ private Builder() { this.planHashMode = null; } - @Nonnull public Builder setParameterHash(int parameterHash) { this.parameterHash = parameterHash; return this; } @SpotBugsSuppressWarnings(value = "EI_EXPOSE_REP2", justification = "Intentional") - @Nonnull public Builder setContinuation(@Nullable final byte[] continuation) { this.continuation = continuation; // copy to be safe? return this; } - @Nonnull public Literals.Builder getLiteralsBuilder() { return literalsBuilder; } - @Nonnull public Builder setForExplain(boolean isForExplain) { this.isForExplain = isForExplain; return this; } - @Nonnull - public Builder setPlanHashMode(@Nonnull PlanHashable.PlanHashMode planHashMode) { + public Builder setPlanHashMode(PlanHashMode planHashMode) { this.planHashMode = planHashMode; return this; } - @Nonnull public NormalizedQueryExecutionContext build() { return new NormalizedQueryExecutionContext(literalsBuilder.build(), continuation, parameterHash, isForExplain, diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/OfflineStoredQueriesProcessor.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/OfflineStoredQueriesProcessor.java index 04777104c60..2758850c97b 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/OfflineStoredQueriesProcessor.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/OfflineStoredQueriesProcessor.java @@ -41,9 +41,7 @@ import com.codahale.metrics.MetricRegistry; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -84,9 +82,8 @@ private OfflineStoredQueriesProcessor() { * this method only reads. Any exception from catalog access is caught and logged at error * level, and an empty list is returned in that case. */ - @Nonnull - public static List getSchemaTemplates(@Nonnull final StoreCatalog storeCatalog, - @Nonnull final Transaction txn) { + public static List getSchemaTemplates(final StoreCatalog storeCatalog, + final Transaction txn) { final List result = new ArrayList<>(); try (var rs = storeCatalog.getSchemaTemplateCatalog().listTemplates(txn)) { while (rs.next()) { @@ -118,9 +115,9 @@ public static List getSchemaTemplates(@Nonnull final * logged at {@code ERROR} level, and is also surfaced as a metric: per-query failures bump * {@link RelationalMetric.RelationalCount#OFFLINE_STORED_QUERIES_QUERIES_FAILED}.

*/ - public static void planStoredQueriesForSchemaTemplates(@Nonnull final RelationalPlanCache cache, - @Nonnull final MetricRegistry metricRegistry, - @Nonnull final List templates) { + public static void planStoredQueriesForSchemaTemplates(final RelationalPlanCache cache, + final MetricRegistry metricRegistry, + final List templates) { final MetricCollector metricCollector = StoreTimerMetricCollector.fromMetricRegistry(metricRegistry); final Counts counts; try { @@ -155,10 +152,9 @@ public static void planStoredQueriesForSchemaTemplates(@Nonnull final Relational } } - @Nonnull - private static Counts planStoredQueriesForSchemaTemplatesAll(@Nonnull final RelationalPlanCache cache, - @Nonnull final MetricCollector metricCollector, - @Nonnull final List templates) { + private static Counts planStoredQueriesForSchemaTemplatesAll(final RelationalPlanCache cache, + final MetricCollector metricCollector, + final List templates) { final Counts counts = new Counts(); for (final RecordLayerSchemaTemplate template : templates) { planStoredQueriesForSchemaTemplate(cache, metricCollector, template, counts); @@ -173,10 +169,10 @@ private static Counts planStoredQueriesForSchemaTemplatesAll(@Nonnull final Rela * template carries them when the SELECT body is planned. Per-query and per-temp-function * outcomes are reported by {@link #planStoredQuery} directly into {@code counts}. */ - private static void planStoredQueriesForSchemaTemplate(@Nonnull final RelationalPlanCache cache, - @Nonnull final MetricCollector metricCollector, - @Nonnull final RecordLayerSchemaTemplate template, - @Nonnull final Counts counts) { + private static void planStoredQueriesForSchemaTemplate(final RelationalPlanCache cache, + final MetricCollector metricCollector, + final RecordLayerSchemaTemplate template, + final Counts counts) { final String templateKey = template.getName() + ":" + template.getVersion(); for (final var entry : template.getStoredQueries().entrySet()) { planStoredQuery(cache, metricCollector, template, templateKey, entry.getKey(), entry.getValue(), counts); @@ -199,13 +195,13 @@ private static void planStoredQueriesForSchemaTemplate(@Nonnull final Relational * {@link RuntimeException} (e.g. {@code UncheckedRelationalException}) from {@code getPlan} * are swallowed so one bad query cannot abort the enclosing template's iteration. */ - private static void planStoredQuery(@Nonnull final RelationalPlanCache cache, - @Nonnull final MetricCollector metricCollector, - @Nonnull final RecordLayerSchemaTemplate template, - @Nonnull final String templateKey, - @Nonnull final String storedQueryName, - @Nonnull final StoredQuery storedQuery, - @Nonnull final Counts counts) { + private static void planStoredQuery(final RelationalPlanCache cache, + final MetricCollector metricCollector, + final RecordLayerSchemaTemplate template, + final String templateKey, + final String storedQueryName, + final StoredQuery storedQuery, + final Counts counts) { final var tempFuncFactory = new MetadataTempFuncFactory(); RecordLayerSchemaTemplate currentTemplate = template; @@ -269,19 +265,17 @@ private static final class MetadataTempFuncFactory extends AbstractMetadataOpera @Nullable private RecordLayerInvokedRoutine invokedRoutine; - @Nonnull @Override - public ConstantAction getCreateTemporaryFunctionConstantAction(@Nonnull final SchemaTemplate templateArg, + public ConstantAction getCreateTemporaryFunctionConstantAction(final SchemaTemplate templateArg, final boolean throwIfExists, - @Nonnull final RecordLayerInvokedRoutine invokedRoutine) { + final RecordLayerInvokedRoutine invokedRoutine) { this.invokedRoutine = invokedRoutine; return txn -> { // no-op: offline path applies its side-effect via updateTemplate() }; } - @Nonnull - RecordLayerSchemaTemplate updateTemplate(@Nonnull final RecordLayerSchemaTemplate template) { + RecordLayerSchemaTemplate updateTemplate(final RecordLayerSchemaTemplate template) { final var routine = this.invokedRoutine; this.invokedRoutine = null; if (routine == null) { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/OptionsUtils.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/OptionsUtils.java index c0fb5733f5b..5b1fc2e56ea 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/OptionsUtils.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/OptionsUtils.java @@ -28,24 +28,20 @@ import com.apple.foundationdb.relational.api.exceptions.ErrorCode; import com.apple.foundationdb.relational.api.exceptions.RelationalException; import com.google.common.collect.ImmutableSet; - -import javax.annotation.Nonnull; import java.util.Arrays; import java.util.Set; @API(API.Status.INTERNAL) public final class OptionsUtils { - @Nonnull - public static PlanHashable.PlanHashMode getCurrentPlanHashMode(@Nonnull final Options options) { + public static PlanHashable.PlanHashMode getCurrentPlanHashMode(final Options options) { final String planHashModeAsString = options.getOption(Options.Name.CURRENT_PLAN_HASH_MODE); return planHashModeAsString == null ? PlanHashable.CURRENT_FOR_CONTINUATION : PlanHashable.PlanHashMode.valueOf(planHashModeAsString); } - @Nonnull - public static Set getValidPlanHashModes(@Nonnull final Options options) { + public static Set getValidPlanHashModes(final Options options) { final String planHashModesAsString = options.getOption(Options.Name.VALID_PLAN_HASH_MODES); if (planHashModesAsString == null) { return ImmutableSet.of(PlanHashable.CURRENT_FOR_CONTINUATION); @@ -56,8 +52,7 @@ public static Set getValidPlanHashModes(@Nonnull fina .collect(ImmutableSet.toImmutableSet()); } - @Nonnull - public static IndexFetchMethod getIndexFetchMethod(@Nonnull final Options options) { + public static IndexFetchMethod getIndexFetchMethod(final Options options) { Options.IndexFetchMethod indexFetchMethod = options.getOption(Options.Name.INDEX_FETCH_METHOD); if (indexFetchMethod == null) { return IndexFetchMethod.USE_REMOTE_FETCH_WITH_FALLBACK; @@ -75,8 +70,7 @@ public static IndexFetchMethod getIndexFetchMethod(@Nonnull final Options option } } - @Nonnull - public static VectorIndexEnginePreference getVectorIndexEnginePreference(@Nonnull final Options options) { + public static VectorIndexEnginePreference getVectorIndexEnginePreference(final Options options) { final Options.VectorIndexEnginePreference preference = options.getOption(Options.Name.VECTOR_INDEX_ENGINE_PREFERENCE); if (preference == null) { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/OrderByExpression.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/OrderByExpression.java index 00b9195aaa3..01133171fc8 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/OrderByExpression.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/OrderByExpression.java @@ -29,8 +29,6 @@ import com.apple.foundationdb.record.query.plan.cascades.values.Value; import com.apple.foundationdb.relational.util.Assert; import com.google.common.collect.Iterables; - -import javax.annotation.Nonnull; import java.util.List; import java.util.Optional; import java.util.Set; @@ -39,43 +37,38 @@ @API(API.Status.EXPERIMENTAL) public final class OrderByExpression { - @Nonnull private final Expression expression; private final boolean descending; private final boolean nullsLast; - private OrderByExpression(@Nonnull Expression expression, boolean descending, boolean nullsLast) { + private OrderByExpression(Expression expression, boolean descending, boolean nullsLast) { this.expression = expression; this.descending = descending; this.nullsLast = nullsLast; } - @Nonnull public Expression getExpression() { return expression; } - @Nonnull @SuppressWarnings("PMD.CompareObjectsWithEquals") - private OrderByExpression withExpression(@Nonnull Expression expression) { + private OrderByExpression withExpression(Expression expression) { if (this.expression == expression) { return this; } return new OrderByExpression(expression, descending, nullsLast); } - @Nonnull - public static OrderByExpression of(@Nonnull Expression expression, boolean descending, boolean nullsLast) { + public static OrderByExpression of(Expression expression, boolean descending, boolean nullsLast) { return new OrderByExpression(expression, descending, nullsLast); } @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - @Nonnull - public static Stream pullUp(@Nonnull final Stream orderBys, - @Nonnull final Value value, - @Nonnull final CorrelationIdentifier correlationIdentifier, - @Nonnull final Set constantAliases, - @Nonnull final Optional qualifier) { + public static Stream pullUp(final Stream orderBys, + final Value value, + final CorrelationIdentifier correlationIdentifier, + final Set constantAliases, + final Optional qualifier) { final var aliasMap = AliasMap.identitiesFor(value.getCorrelatedTo()); final var simplifiedValue = value.simplify(EvaluationContext.empty(), aliasMap, constantAliases); return orderBys @@ -111,7 +104,6 @@ public static Stream pullUp(@Nonnull final Stream toOrderingParts(@Nonnull Stream orderBys, - @Nonnull CorrelationIdentifier rebaseSource, - @Nonnull CorrelationIdentifier rebaseTarget) { + public static Stream toOrderingParts(Stream orderBys, + CorrelationIdentifier rebaseSource, + CorrelationIdentifier rebaseTarget) { final var aliasMap = AliasMap.ofAliases(rebaseSource, rebaseTarget); return orderBys.map(orderBy -> { final var rebased = orderBy.getExpression().getUnderlying().rebase(aliasMap); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/OrderedLiteral.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/OrderedLiteral.java index 935671eff74..058a74ac6c1 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/OrderedLiteral.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/OrderedLiteral.java @@ -27,9 +27,7 @@ import com.apple.foundationdb.relational.util.Assert; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Verify; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.Comparator; import java.util.Objects; import java.util.Optional; @@ -52,7 +50,6 @@ public class OrderedLiteral { return Integer.compare(o1.getTokenIndex(), o2.getTokenIndex()); }; - @Nonnull private final Type type; @Nullable @@ -72,12 +69,11 @@ public class OrderedLiteral { /** * The scope that the literal is defined within. It can be empty. */ - @Nonnull private final Optional scope; - OrderedLiteral(@Nonnull final Type type, @Nullable final Object literalObject, + OrderedLiteral(final Type type, @Nullable final Object literalObject, @Nullable final Integer unnamedParameterIndex, @Nullable final String parameterName, - final int tokenIndex, @Nonnull Optional scope) { + final int tokenIndex, Optional scope) { Verify.verify(unnamedParameterIndex == null || parameterName == null); this.type = type; this.literalObject = literalObject; @@ -87,7 +83,6 @@ public class OrderedLiteral { this.scope = scope; } - @Nonnull public Type getType() { return type; } @@ -115,12 +110,10 @@ public boolean isScoped() { return scope.isPresent(); } - @Nonnull public Optional getScopeMaybe() { return scope; } - @Nonnull public String getConstantId() { return constantId(tokenIndex, getScopeMaybe()); } @@ -157,7 +150,7 @@ public int hashCode() { return Objects.hash(tokenIndex); } - public boolean deepEquals(@Nonnull final OrderedLiteral other) { + public boolean deepEquals(final OrderedLiteral other) { return this.equals(other) && Objects.equals(parameterName, other.parameterName) && Objects.equals(unnamedParameterIndex, other.unnamedParameterIndex) @@ -173,8 +166,7 @@ public String toString() { literalObject + "@" + scope.orElse("") + tokenIndex; } - @Nonnull - TypedQueryArgument toProto(@Nonnull final PlanSerializationContext serializationContext, int literalTableIndex) { + TypedQueryArgument toProto(final PlanSerializationContext serializationContext, int literalTableIndex) { final var type = getType(); final var argumentBuilder = TypedQueryArgument.newBuilder() .setType(type.toTypeProto(serializationContext)) @@ -194,30 +186,26 @@ TypedQueryArgument toProto(@Nonnull final PlanSerializationContext serialization return argumentBuilder.build(); } - @Nonnull - private static OrderedLiteral forQueryLiteral(@Nonnull final Type type, @Nullable final Object literalObject, final int tokenIndex, - @Nonnull final Optional scope) { + private static OrderedLiteral forQueryLiteral(final Type type, @Nullable final Object literalObject, final int tokenIndex, + final Optional scope) { return new OrderedLiteral(type, literalObject, null, null, tokenIndex, scope); } - @Nonnull - private static OrderedLiteral forUnnamedParameter(@Nonnull final Type type, @Nullable final Object literalObject, + private static OrderedLiteral forUnnamedParameter(final Type type, @Nullable final Object literalObject, final int unnamedParameterIndex, final int tokenIndex, - @Nonnull final Optional scope) { + final Optional scope) { return new OrderedLiteral(type, literalObject, unnamedParameterIndex, null, tokenIndex, scope); } - @Nonnull - private static OrderedLiteral forNamedParameter(@Nonnull final Type type, @Nullable final Object literalObject, - @Nonnull final String parameterName, final int tokenIndex, - @Nonnull final Optional scope) { + private static OrderedLiteral forNamedParameter(final Type type, @Nullable final Object literalObject, + final String parameterName, final int tokenIndex, + final Optional scope) { return new OrderedLiteral(type, literalObject, null, parameterName, tokenIndex, scope); } - @Nonnull - public static OrderedLiteral fromProto(@Nonnull final PlanSerializationContext serializationContext, - @Nonnull final TypeRepository typeRepository, - @Nonnull final TypedQueryArgument argumentProto) { + public static OrderedLiteral fromProto(final PlanSerializationContext serializationContext, + final TypeRepository typeRepository, + final TypedQueryArgument argumentProto) { final var argumentType = Type.fromTypeProto(serializationContext, argumentProto.getType()); final Optional scopeMaybe = argumentProto.hasScope() ? Optional.of(argumentProto.getScope()) : Optional.empty(); if (argumentProto.hasUnnamedParameterIndex()) { @@ -235,12 +223,10 @@ public static OrderedLiteral fromProto(@Nonnull final PlanSerializationContext s } } - @Nonnull - public static String constantId(final int tokenIndex, @Nonnull final Optional scope) { + public static String constantId(final int tokenIndex, final Optional scope) { return "c" + scope.orElse("") + tokenIndex; } - @Nonnull @VisibleForTesting public static String constantId(final int tokenIndex) { return constantId(tokenIndex, Optional.empty()); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ParseHelpers.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ParseHelpers.java index 88fa8466a42..bebc96fe6bc 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ParseHelpers.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ParseHelpers.java @@ -38,13 +38,13 @@ import org.antlr.v4.runtime.Recognizer; import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.tree.ParseTree; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.Base64; import java.util.Locale; import java.util.function.Supplier; +import static com.apple.foundationdb.relational.generated.RelationalParser.OrderClauseContext; + /** * Contains a set of utility methods that are relevant for parsing the AST. * TODO: this class should be removed. @@ -53,7 +53,6 @@ public final class ParseHelpers { // used only to be passed to expression lambdas in Record Layer (to be removed). - @Nonnull public static final TypeRepository EMPTY_TYPE_REPOSITORY = TypeRepository.empty(); private ParseHelpers() { @@ -64,8 +63,7 @@ private ParseHelpers() { * @param valueAsString The value to parse. * @return The corresponding typed and literal {@link Value} object */ - @Nonnull - public static Object parseDecimal(@Nonnull String valueAsString) { + public static Object parseDecimal(String valueAsString) { final var lastCharIdx = valueAsString.length() - 1; Assert.thatUnchecked(lastCharIdx >= 0); if (valueAsString.contains(".")) { @@ -103,9 +101,8 @@ public static Object parseDecimal(@Nonnull String valueAsString) { } } - @Nonnull - public static String underlineParsingError(@Nonnull Recognizer recognizer, - @Nonnull Token offendingToken, + public static String underlineParsingError(Recognizer recognizer, + Token offendingToken, int line, int charPositionInLine) { // I got this recipe from the book: "The Definitive ANTLR 4 Reference, 2nd Edition". @@ -126,7 +123,7 @@ public static String underlineParsingError(@Nonnull Recognizer recognizer, return stringBuilder.toString(); } - public static boolean isConstant(@Nonnull final RelationalParser.ExpressionsContext expressionsContext) { + public static boolean isConstant(final RelationalParser.ExpressionsContext expressionsContext) { for (final var exp : expressionsContext.expression()) { if (!(exp instanceof RelationalParser.PredicatedExpressionContext)) { return false; @@ -143,7 +140,6 @@ public static boolean isConstant(@Nonnull final RelationalParser.ExpressionsCont return true; } - @Nonnull public static byte[] parseBytes(String text) { try { if (text.toLowerCase(Locale.ROOT).startsWith("xstartswith_") && text.endsWith("'")) { @@ -164,14 +160,14 @@ public static byte[] parseBytes(String text) { } } - public static boolean isNullsLast(@Nullable RelationalParser.OrderClauseContext orderClause, boolean isDescending) { + public static boolean isNullsLast(@Nullable OrderClauseContext orderClause, boolean isDescending) { if (orderClause == null || orderClause.nulls == null) { return isDescending; // Default behavior: ASC NULLS FIRST, DESC NULLS LAST } return orderClause.LAST() != null; } - public static boolean isDescending(@Nullable RelationalParser.OrderClauseContext orderClause) { + public static boolean isDescending(@Nullable OrderClauseContext orderClause) { if (orderClause == null) { return false; // Default is ASC } @@ -180,29 +176,24 @@ public static boolean isDescending(@Nullable RelationalParser.OrderClauseContext public static class ParseTreeLikeAdapter implements TreeLike { - @Nonnull private final ParseTree parseTree; - @Nonnull private final Supplier> children; - private ParseTreeLikeAdapter(@Nonnull final ParseTree parseTree) { + private ParseTreeLikeAdapter(final ParseTree parseTree) { this.parseTree = parseTree; this.children = Suppliers.memoize(this::computeChildren); } - @Nonnull @Override public ParseTreeLikeAdapter getThis() { return this; } - @Nonnull public ParseTree getParseTree() { return parseTree; } - @Nonnull public Iterable computeChildren() { final var result = ImmutableList.builder(); for (int i = 0; i < parseTree.getChildCount(); i++) { @@ -212,20 +203,17 @@ public Iterable computeChildren() { } - @Nonnull @Override public Iterable getChildren() { return children.get(); } - @Nonnull @Override public ParseTreeLikeAdapter withChildren(Iterable iterable) { throw new UnsupportedOperationException("adding children to parse tree is not supported"); } - @Nonnull - public static ParseTreeLikeAdapter from(@Nonnull final ParseTree parseTree) { + public static ParseTreeLikeAdapter from(final ParseTree parseTree) { return new ParseTreeLikeAdapter(parseTree); } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ParseTreeInfoImpl.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ParseTreeInfoImpl.java index c33cc2cdea4..8c7c2979884 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ParseTreeInfoImpl.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ParseTreeInfoImpl.java @@ -32,8 +32,6 @@ import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.RuleNode; import org.antlr.v4.runtime.tree.TerminalNode; - -import javax.annotation.Nonnull; import java.util.ArrayDeque; import java.util.Deque; @@ -43,23 +41,20 @@ @API(API.Status.EXPERIMENTAL) public final class ParseTreeInfoImpl implements ParseTreeInfo { - @Nonnull private final ParseTree rootContext; - @Nonnull private final QueryType queryType; - private ParseTreeInfoImpl(@Nonnull final ParseTree effectiveContext, @Nonnull final QueryType queryType) { + private ParseTreeInfoImpl(final ParseTree effectiveContext, final QueryType queryType) { this.rootContext = effectiveContext; this.queryType = queryType; } private static class QueryTypeVisitor extends RelationalParserBaseVisitor { - @Nonnull private final ParseTree rootContext; - private QueryTypeVisitor(@Nonnull final ParseTree rootContext) { + private QueryTypeVisitor(final ParseTree rootContext) { this.rootContext = rootContext; } @@ -110,7 +105,7 @@ public ParseTreeInfoImpl visitChildren(final RuleNode node) { return new ParseTreeInfoImpl(rootContext, QueryType.OTHER); } - private static void remapParseTree(@Nonnull final ParseTree src) { + private static void remapParseTree(final ParseTree src) { final int offset = src instanceof TerminalNode ? ((TerminalNode) src).getSymbol().getTokenIndex() : ((ParserRuleContext) src).start.getTokenIndex(); @@ -145,19 +140,16 @@ protected ParseTreeInfoImpl aggregateResult(ParseTreeInfoImpl aggregate, ParseTr } } - @Nonnull @Override public QueryType getQueryType() { return queryType; } - @Nonnull public ParseTree getRootContext() { return rootContext; } - @Nonnull - public static ParseTreeInfoImpl from(@Nonnull final RelationalParser.RootContext root) { + public static ParseTreeInfoImpl from(final RelationalParser.RootContext root) { return new QueryTypeVisitor(root).visit(root); } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Plan.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Plan.java index f3d02563d7c..ec6a3aa7b10 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Plan.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Plan.java @@ -29,48 +29,38 @@ import com.apple.foundationdb.relational.api.exceptions.RelationalException; import com.apple.foundationdb.relational.api.metrics.MetricCollector; import com.apple.foundationdb.relational.api.metrics.RelationalMetric; - -import javax.annotation.Nonnull; - public abstract class Plan { - @Nonnull protected final String query; - protected Plan(@Nonnull final String query) { + protected Plan(final String query) { this.query = query; } public static class ExecutionContext { - @Nonnull final Transaction transaction; - @Nonnull final Options options; - @Nonnull final RelationalConnection connection; - @Nonnull final MetricCollector metricCollector; - ExecutionContext(@Nonnull Transaction transaction, - @Nonnull Options options, - @Nonnull RelationalConnection connection, - @Nonnull MetricCollector metricCollector) { + ExecutionContext(Transaction transaction, + Options options, + RelationalConnection connection, + MetricCollector metricCollector) { this.transaction = transaction; this.options = options; this.connection = connection; this.metricCollector = metricCollector; } - @Nonnull public Options getOptions() { return options; } - @Nonnull - public static ExecutionContext of(@Nonnull Transaction transaction, - @Nonnull Options options, - @Nonnull RelationalConnection connection, - @Nonnull MetricCollector metricCollector) { + public static ExecutionContext of(Transaction transaction, + Options options, + RelationalConnection connection, + MetricCollector metricCollector) { return new ExecutionContext(transaction, options, connection, metricCollector); } } @@ -83,8 +73,8 @@ public static ExecutionContext of(@Nonnull Transaction transaction, */ public abstract boolean isUpdatePlan(); - public abstract Plan optimize(@Nonnull CascadesPlanner planner, @Nonnull PlanContext planContext, - @Nonnull PlanHashable.PlanHashMode currentPlanHashMode) throws RelationalException; + public abstract Plan optimize(CascadesPlanner planner, PlanContext planContext, + PlanHashable.PlanHashMode currentPlanHashMode) throws RelationalException; /** * Executes a particular type of Plan. If the plan "can" be executed, it should be timed and registered as @@ -95,22 +85,18 @@ public abstract Plan optimize(@Nonnull CascadesPlanner planner, @Nonnull Plan * @return The result of the query execution, if there. * @throws RelationalException if something goes wrong. */ - public final T execute(@Nonnull final ExecutionContext c) throws RelationalException { + public final T execute(final ExecutionContext c) throws RelationalException { return c.metricCollector.clock(RelationalMetric.RelationalEvent.TOTAL_EXECUTE_QUERY, () -> executeInternal(c)); } - protected abstract T executeInternal(@Nonnull ExecutionContext c) throws RelationalException; + protected abstract T executeInternal(ExecutionContext c) throws RelationalException; - @Nonnull public abstract QueryPlanConstraint getConstraint(); - @Nonnull - public abstract Plan withExecutionContext(@Nonnull QueryExecutionContext queryExecutionContext); + public abstract Plan withExecutionContext(QueryExecutionContext queryExecutionContext); - @Nonnull public abstract String explain(); - @Nonnull public String getQuery() { return query; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanContext.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanContext.java index dc378be52a7..734d8be0aaa 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanContext.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanContext.java @@ -34,8 +34,6 @@ import com.apple.foundationdb.relational.recordlayer.AbstractDatabase; import com.apple.foundationdb.relational.util.Assert; import com.google.common.annotations.VisibleForTesting; - -import javax.annotation.Nonnull; import java.net.URI; import java.util.Optional; import java.util.Set; @@ -45,21 +43,13 @@ public final class PlanContext { // todo (yhatem) remove this if possible. - @Nonnull private final RecordMetaData metaData; - @Nonnull private final MetricCollector metricCollector; - @Nonnull private final PlannerConfiguration plannerConfiguration; - @Nonnull private final MetadataOperationsFactory metadataOperationsFactory; - @Nonnull private final DdlQueryFactory ddlQueryFactory; - @Nonnull private final URI dbUri; - @Nonnull private final PreparedParams preparedStatementParameters; - @Nonnull private final SchemaTemplate schemaTemplate; private final boolean isCaseSensitive; @@ -78,14 +68,14 @@ public final class PlanContext { * @param isCaseSensitive {@code True} if SQL identifiers should be treated as case-sensitive, otherwise * {@code false}. **/ - private PlanContext(@Nonnull RecordMetaData metaData, - @Nonnull MetricCollector metricCollector, - @Nonnull SchemaTemplate schemaTemplate, - @Nonnull PlannerConfiguration plannerConfiguration, - @Nonnull MetadataOperationsFactory metadataOperationsFactory, - @Nonnull DdlQueryFactory ddlQueryFactory, - @Nonnull URI dbUri, - @Nonnull PreparedParams preparedStatementParameters, + private PlanContext(RecordMetaData metaData, + MetricCollector metricCollector, + SchemaTemplate schemaTemplate, + PlannerConfiguration plannerConfiguration, + MetadataOperationsFactory metadataOperationsFactory, + DdlQueryFactory ddlQueryFactory, + URI dbUri, + PreparedParams preparedStatementParameters, boolean isCaseSensitive) { this.metaData = metaData; this.metricCollector = metricCollector; @@ -98,57 +88,46 @@ private PlanContext(@Nonnull RecordMetaData metaData, this.isCaseSensitive = isCaseSensitive; } - @Nonnull public RecordMetaData getMetaData() { return metaData; } - @Nonnull public MetricCollector getMetricsCollector() { return metricCollector; } - @Nonnull public PlannerConfiguration getPlannerConfiguration() { return plannerConfiguration; } - @Nonnull public Optional> getReadableIndexes() { return plannerConfiguration.getReadableIndexes(); } - @Nonnull public RecordQueryPlannerConfiguration getRecordQueryPlannerConfiguration() { return plannerConfiguration.getRecordQueryPlannerConfiguration(); } - @Nonnull public MetadataOperationsFactory getConstantActionFactory() { return metadataOperationsFactory; } - @Nonnull public DdlQueryFactory getDdlQueryFactory() { return ddlQueryFactory; } - @Nonnull public URI getDbUri() { return dbUri; } - @Nonnull public PreparedParams getPreparedStatementParameters() { return preparedStatementParameters; } - @Nonnull public SchemaTemplate getSchemaTemplate() { return schemaTemplate; } - @Nonnull public static Builder builder() { return new Builder(); } @@ -176,66 +155,56 @@ public static final class Builder { private Builder() { } - @Nonnull @VisibleForTesting - public Builder withMetadata(@Nonnull RecordMetaData metadata) { + public Builder withMetadata(RecordMetaData metadata) { this.metaData = metadata; return this; } - @Nonnull - public Builder withMetricsCollector(@Nonnull MetricCollector metricCollector) { + public Builder withMetricsCollector(MetricCollector metricCollector) { this.metricCollector = metricCollector; return this; } - @Nonnull - public Builder withSchemaTemplate(@Nonnull SchemaTemplate schemaTemplate) { + public Builder withSchemaTemplate(SchemaTemplate schemaTemplate) { this.schemaTemplate = schemaTemplate; return this; } - @Nonnull @VisibleForTesting - public Builder withPlannerConfiguration(@Nonnull PlannerConfiguration plannerConfiguration) { + public Builder withPlannerConfiguration(PlannerConfiguration plannerConfiguration) { this.plannerConfiguration = plannerConfiguration; return this; } - @Nonnull private Builder isCaseSensitive(boolean isCaseSensitive) { this.isCaseSensitive = isCaseSensitive; return this; } - @Nonnull @VisibleForTesting - public Builder withConstantActionFactory(@Nonnull MetadataOperationsFactory metadataOperationsFactory) { + public Builder withConstantActionFactory(MetadataOperationsFactory metadataOperationsFactory) { this.metadataOperationsFactory = metadataOperationsFactory; return this; } - @Nonnull - public Builder withDdlQueryFactory(@Nonnull DdlQueryFactory ddlQueryFactory) { + public Builder withDdlQueryFactory(DdlQueryFactory ddlQueryFactory) { this.ddlQueryFactory = ddlQueryFactory; return this; } - @Nonnull - public Builder withDbUri(@Nonnull URI dbUri) { + public Builder withDbUri(URI dbUri) { this.dbUri = dbUri; return this; } - @Nonnull - public Builder withPreparedParameters(@Nonnull PreparedParams parameters) { + public Builder withPreparedParameters(PreparedParams parameters) { this.preparedStatementParameters = parameters; return this; } - @Nonnull - private static Optional> getReadableIndexes(@Nonnull RecordMetaData metaData, - @Nonnull RecordStoreState storeState) { + private static Optional> getReadableIndexes(RecordMetaData metaData, + RecordStoreState storeState) { // (yhatem) we should cache this somewhere, or embed it in the caching logic of the {@code FDBRecordStoreBase#createOrOpen}. if (storeState.allIndexesReadable()) { return Optional.empty(); @@ -246,15 +215,13 @@ private static Optional> getReadableIndexes(@Nonnull RecordMetaData } } - @Nonnull - public Builder fromRecordStore(@Nonnull FDBRecordStoreBase recordStore, @Nonnull final Options options) { + public Builder fromRecordStore(FDBRecordStoreBase recordStore, final Options options) { return fromMetaDataAndState(recordStore.getRecordMetaData(), recordStore.getRecordStoreState(), options); } - @Nonnull - public Builder fromMetaDataAndState(@Nonnull RecordMetaData metaData, - @Nonnull RecordStoreState recordStoreState, - @Nonnull final Options options) { + public Builder fromMetaDataAndState(RecordMetaData metaData, + RecordStoreState recordStoreState, + final Options options) { final var plannerConfig = recordStoreState.allIndexesReadable() ? PlannerConfiguration.ofAllAvailableIndexes(options) : PlannerConfiguration.of(getReadableIndexes(metaData, recordStoreState), options); @@ -263,8 +230,7 @@ public Builder fromMetaDataAndState(@Nonnull RecordMetaData metaData, .isCaseSensitive(options.getOption(Options.Name.CASE_SENSITIVE_IDENTIFIERS)); } - @Nonnull - public Builder fromDatabase(@Nonnull AbstractDatabase database) { + public Builder fromDatabase(AbstractDatabase database) { return withDdlQueryFactory(database.getDdlQueryFactory()) .withConstantActionFactory(database.getDdlFactory()) .withDbUri(database.getURI()); @@ -282,21 +248,18 @@ private void verify() throws RelationalException { } } - @Nonnull public PlanContext build() throws RelationalException { verify(); return new PlanContext(metaData, metricCollector, schemaTemplate, plannerConfiguration, metadataOperationsFactory, ddlQueryFactory, dbUri, preparedStatementParameters, isCaseSensitive); } - @Nonnull public static Builder create() { return new Builder(); } @VisibleForTesting - @Nonnull - public static Builder unapply(@Nonnull PlanContext planContext) { + public static Builder unapply(PlanContext planContext) { return create().withConstantActionFactory(planContext.metadataOperationsFactory) .withDbUri(planContext.dbUri) .withMetadata(planContext.metaData) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanGenerator.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanGenerator.java index 047c2a81420..38821abb5c2 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanGenerator.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanGenerator.java @@ -68,8 +68,6 @@ import com.google.protobuf.InvalidProtocolBufferException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; - -import javax.annotation.Nonnull; import java.net.URI; import java.sql.SQLException; import java.util.Arrays; @@ -94,26 +92,22 @@ public final class PlanGenerator { * An optional plan cache used to improve performance by storing execution plans. * This allows the system to reuse plans for identical queries, avoiding redundant planning. */ - @Nonnull private final Optional cache; - @Nonnull private final CascadesPlanner planner; - @Nonnull private final PlanContext planContext; - @Nonnull private Options options; private long beginTime = System.nanoTime(); private long currentTime = beginTime; - private PlanGenerator(@Nonnull final Optional cache, - @Nonnull final PlanContext planContext, - @Nonnull final CascadesPlanner planner, - @Nonnull final Options options) { + private PlanGenerator(final Optional cache, + final PlanContext planContext, + final CascadesPlanner planner, + final Options options) { this.cache = cache; this.planContext = planContext; this.planner = planner; @@ -130,13 +124,11 @@ private PlanGenerator(@Nonnull final Optional cache, * @return a corresponding {@link Plan}. * @throws RelationalException If planning was unsuccessful. */ - @Nonnull - public Plan getPlan(@Nonnull final String query) throws RelationalException { + public Plan getPlan(final String query) throws RelationalException { return getPlan(query, Map.of()); } - @Nonnull - public Plan getPlan(@Nonnull final String query, @Nonnull final Map logContext) throws RelationalException { + public Plan getPlan(final String query, final Map logContext) throws RelationalException { final KeyValueLogMessage message = KeyValueLogMessage.build("PlanGenerator"); message.addKeysAndValues(logContext); resetTimer(); @@ -157,8 +149,7 @@ private boolean isCaseSensitive() { return options.getOption(Options.Name.CASE_SENSITIVE_IDENTIFIERS); } - @Nonnull - private Plan getPlanInternal(@Nonnull String query, @Nonnull KeyValueLogMessage message) throws RelationalException { + private Plan getPlanInternal(String query, KeyValueLogMessage message) throws RelationalException { try { // parse query, generate AST, extract literals from AST, hash it w.r.t. prepared parameters, and identify query caching behavior flags final Set validPlanHashModes = OptionsUtils.getValidPlanHashModes(options); @@ -229,10 +220,9 @@ private Plan getPlanInternal(@Nonnull String query, @Nonnull KeyValueLogMessa } } - @Nonnull - private Plan generatePhysicalPlan(@Nonnull AstNormalizer.NormalizationResult ast, - @Nonnull Set validPlanHashModes, - @Nonnull PlanHashable.PlanHashMode currentPlanHashMode) throws RelationalException { + private Plan generatePhysicalPlan(AstNormalizer.NormalizationResult ast, + Set validPlanHashModes, + PlanHashable.PlanHashMode currentPlanHashMode) throws RelationalException { if (ast.getQueryCachingFlags().contains(AstNormalizer.NormalizationResult.QueryCachingFlags.IS_EXECUTE_CONTINUATION_STATEMENT)) { return planContext.getMetricsCollector().clock(RelationalMetric.RelationalEvent.GENERATE_CONTINUED_PLAN, () -> generatePhysicalPlanForExecuteContinuation(ast, validPlanHashModes, currentPlanHashMode)); @@ -241,16 +231,14 @@ private Plan generatePhysicalPlan(@Nonnull AstNormalizer.NormalizationResult } } - @Nonnull public PlannerConfiguration getPlannerConfigurations() { return planContext.getPlannerConfiguration(); } - @Nonnull @SuppressWarnings("try") - private Plan generatePhysicalPlanForCompilableStatement(@Nonnull AstNormalizer.NormalizationResult ast, + private Plan generatePhysicalPlanForCompilableStatement(AstNormalizer.NormalizationResult ast, boolean caseSensitive, - @Nonnull PlanHashable.PlanHashMode currentPlanHashMode) { + PlanHashable.PlanHashMode currentPlanHashMode) { // The hash value used accounts for the values that identify the query and not part of the execution context (e.g. // literal and parameter values without LIMIT and CONTINUATION) final var parameterHash = ast.getQueryExecutionContext().getParameterHash(); @@ -277,10 +265,9 @@ private Plan generatePhysicalPlanForCompilableStatement(@Nonnull AstNormalize } } - @Nonnull - private Plan generatePhysicalPlanForExecuteContinuation(@Nonnull AstNormalizer.NormalizationResult ast, - @Nonnull Set validPlanHashModes, - @Nonnull PlanHashable.PlanHashMode currentPlanHashMode) + private Plan generatePhysicalPlanForExecuteContinuation(AstNormalizer.NormalizationResult ast, + Set validPlanHashModes, + PlanHashable.PlanHashMode currentPlanHashMode) throws RelationalException { final var queryHasherContext = ast.getQueryExecutionContext(); final var continuationProto = queryHasherContext.getContinuation(); @@ -301,11 +288,10 @@ private Plan generatePhysicalPlanForExecuteContinuation(@Nonnull AstNormalize } } - @Nonnull private static CopyPlan generatePhysicalPlanForCopyContinuation( - @Nonnull final AstNormalizer.NormalizationResult ast, - @Nonnull final PlanHashable.PlanHashMode currentPlanHashMode, - @Nonnull final ContinuationImpl continuation) throws PlanValidator.PlanValidationException { + final AstNormalizer.NormalizationResult ast, + final PlanHashable.PlanHashMode currentPlanHashMode, + final ContinuationImpl continuation) throws PlanValidator.PlanValidationException { final var planGenerationContext = new MutablePlanGenerationContext(PreparedParams.empty(), currentPlanHashMode, ast.getQuery(), @@ -318,11 +304,10 @@ private static CopyPlan generatePhysicalPlanForCopyContinuation( return copyPlan; } - @Nonnull private static QueryPlan.ContinuedPhysicalQueryPlan generatePhysicalPlanForCompiledStatementContinuation( - final @Nonnull AstNormalizer.NormalizationResult ast, - final @Nonnull Set validPlanHashModes, - final @Nonnull PlanHashable.PlanHashMode currentPlanHashMode, + final AstNormalizer.NormalizationResult ast, + final Set validPlanHashModes, + final PlanHashable.PlanHashMode currentPlanHashMode, final ContinuationImpl continuation, final byte[] continuationProto) throws RelationalException { final var compiledStatement = Assert.notNullUnchecked(continuation.getCompiledStatement()); @@ -431,9 +416,8 @@ private long totalTimeMicros() { return TimeUnit.NANOSECONDS.toMicros(System.nanoTime() - beginTime); } - @Nonnull - private static PreparedParams deserializeArgumentsForParameters(@Nonnull final CompiledStatement compiledStatement, - @Nonnull final OrderedLiteral[] orderedLiteralsTable) { + private static PreparedParams deserializeArgumentsForParameters(final CompiledStatement compiledStatement, + final OrderedLiteral[] orderedLiteralsTable) { final var unnamedParameterMap = Maps.newHashMap(); final var namedParameterMap = Maps.newHashMap(); @@ -450,7 +434,6 @@ private static PreparedParams deserializeArgumentsForParameters(@Nonnull final C return PreparedParams.of(unnamedParameterMap, namedParameterMap); } - @Nonnull public Options getOptions() { return options; } @@ -464,7 +447,7 @@ public Options getOptions() { * * @return {@code true} if the query should interact with the plan cache, otherwise {@code false}. */ - private static boolean shouldNotCache(@Nonnull final Set queryCachingFlags) { + private static boolean shouldNotCache(final Set queryCachingFlags) { return queryCachingFlags.contains(AstNormalizer.NormalizationResult.QueryCachingFlags.WITH_NO_CACHE_OPTION) || queryCachingFlags.contains(AstNormalizer.NormalizationResult.QueryCachingFlags.IS_DDL_STATEMENT) || // avoid caching INSERT statements since they could result in extremely large plans leading to potential @@ -484,13 +467,12 @@ private static boolean shouldNotCache(@Nonnull final Set cache, - @Nonnull final PlanContext planContext, - @Nonnull final RecordMetaData metaData, - @Nonnull final RecordStoreState recordStoreState, - @Nonnull final IndexMatchCandidateRegistry matchCandidateRegistry, - @Nonnull final Options options) throws RelationalException { + public static PlanGenerator create(final Optional cache, + final PlanContext planContext, + final RecordMetaData metaData, + final RecordStoreState recordStoreState, + final IndexMatchCandidateRegistry matchCandidateRegistry, + final Options options) throws RelationalException { final var planner = new CascadesPlanner(metaData, recordStoreState, matchCandidateRegistry); planner.setConfiguration(planContext.getRecordQueryPlannerConfiguration()); return new PlanGenerator(cache, planContext, planner, options); @@ -506,11 +488,10 @@ public static PlanGenerator create(@Nonnull final Optional * @return a new instance of the plan generator * @throws RelationalException if creation of the plan generator fails */ - @Nonnull - public static PlanGenerator create(@Nonnull final Optional cache, - @Nonnull final PlanContext planContext, - @Nonnull FDBRecordStoreBase store, - @Nonnull final Options options) throws RelationalException { + public static PlanGenerator create(final Optional cache, + final PlanContext planContext, + FDBRecordStoreBase store, + final Options options) throws RelationalException { return create(cache, planContext, store.getRecordMetaData(), store.getRecordStoreState(), store.getIndexMaintainerRegistry(), options); } @@ -532,12 +513,11 @@ public static PlanGenerator create(@Nonnull final Optional * @return a new plan generator * @throws RelationalException if creation fails */ - @Nonnull - public static PlanGenerator create(@Nonnull final Optional cache, - @Nonnull final RecordLayerSchemaTemplate schemaTemplate, - @Nonnull final RecordStoreState recordStoreState, - @Nonnull final MetricCollector metricCollector, - @Nonnull final Options options) throws RelationalException { + public static PlanGenerator create(final Optional cache, + final RecordLayerSchemaTemplate schemaTemplate, + final RecordStoreState recordStoreState, + final MetricCollector metricCollector, + final Options options) throws RelationalException { final var metaData = schemaTemplate.toRecordMetadata(); final var planContext = PlanContext.Builder.create() .fromMetaDataAndState(metaData, recordStoreState, options) @@ -563,11 +543,10 @@ public static PlanGenerator create(@Nonnull final Optional * @return a new plan generator * @throws RelationalException if creation fails */ - @Nonnull - public static PlanGenerator create(@Nonnull final RecordLayerSchemaTemplate schemaTemplate, - @Nonnull final MetadataOperationsFactory metadataOperationsFactory, - @Nonnull final MetricCollector metricCollector, - @Nonnull final Options options) throws RelationalException { + public static PlanGenerator create(final RecordLayerSchemaTemplate schemaTemplate, + final MetadataOperationsFactory metadataOperationsFactory, + final MetricCollector metricCollector, + final Options options) throws RelationalException { final var metaData = schemaTemplate.toRecordMetadata(); final var recordStoreState = new RecordStoreState(null, null); final var planContext = PlanContext.Builder.create() diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanValidator.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanValidator.java index 2bc4c9f442f..c3e720333b6 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanValidator.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanValidator.java @@ -36,9 +36,7 @@ import com.apple.foundationdb.relational.recordlayer.ContinuationImpl; import com.google.protobuf.Message; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.Objects; import java.util.Set; @@ -49,8 +47,8 @@ public final class PlanValidator { private PlanValidator() { } - public static PlanHashMode validateSerializedPlanSerializationMode(@Nonnull final CompiledStatement compiledStatement, - @Nonnull final Set validPlanHashModes) throws RelationalException { + public static PlanHashMode validateSerializedPlanSerializationMode(final CompiledStatement compiledStatement, + final Set validPlanHashModes) throws RelationalException { final PlanHashable.PlanHashMode planSerializationMode = PlanHashable.PlanHashMode.valueOf(compiledStatement.getPlanSerializationMode()); if (!validPlanHashModes.contains(planSerializationMode)) { @@ -59,8 +57,8 @@ public static PlanHashMode validateSerializedPlanSerializationMode(@Nonnull fina return planSerializationMode; } - public static void validateContinuationConstraint(@Nonnull final FDBRecordStoreBase fdbRecordStore, - @Nonnull final QueryPlanConstraint continuationPlanConstraint) throws RelationalException { + public static void validateContinuationConstraint(final FDBRecordStoreBase fdbRecordStore, + final QueryPlanConstraint continuationPlanConstraint) throws RelationalException { final Boolean isValid = continuationPlanConstraint.getPredicate() .eval(fdbRecordStore, EvaluationContext.EMPTY); @@ -69,12 +67,12 @@ public static void validateContinuationConstraint(@Nonnull f } } - public static void validateHashes(@Nonnull final ContinuationImpl parsedContinuation, - @Nonnull final MetricCollector metricCollector, - @Nonnull final RecordQueryPlan plan, - @Nonnull final QueryExecutionContext context, - @Nonnull final PlanHashMode currentPlanHashMode, - @Nonnull final Set validPlanHashModes) throws RelationalException { + public static void validateHashes(final ContinuationImpl parsedContinuation, + final MetricCollector metricCollector, + final RecordQueryPlan plan, + final QueryExecutionContext context, + final PlanHashMode currentPlanHashMode, + final Set validPlanHashModes) throws RelationalException { // Nothing needs to be validated if this continuation is at the beginning if (!parsedContinuation.atBeginning()) { if (!validateBindingHash(context, parsedContinuation)) { @@ -111,10 +109,10 @@ private static boolean validateBindingHash(QueryExecutionContext parameters, Con * match; {@code null} if no such valid plan hash mode could be resolved. */ @Nullable - private static PlanHashMode resolveValidPlanHashMode(@Nonnull final RecordQueryPlan plan, - @Nonnull final ContinuationImpl continuation, - @Nonnull final PlanHashMode currentPlanHashMode, - @Nonnull final Set validPlanHashModes) { + private static PlanHashMode resolveValidPlanHashMode(final RecordQueryPlan plan, + final ContinuationImpl continuation, + final PlanHashMode currentPlanHashMode, + final Set validPlanHashModes) { if (Objects.equals(plan.planHash(currentPlanHashMode), continuation.getPlanHash())) { return currentPlanHashMode; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlannerConfiguration.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlannerConfiguration.java index 90a2cf4a377..498ff061818 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlannerConfiguration.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlannerConfiguration.java @@ -29,8 +29,6 @@ import com.apple.foundationdb.record.query.plan.cascades.PlanningRuleSet; import com.apple.foundationdb.relational.api.Options; import com.google.common.collect.ImmutableSet; - -import javax.annotation.Nonnull; import java.util.Collection; import java.util.Objects; import java.util.Optional; @@ -52,33 +50,28 @@ @API(API.Status.EXPERIMENTAL) public final class PlannerConfiguration { - @Nonnull private final Optional> readableIndexes; - @Nonnull private final IndexFetchMethod indexFetchMethod; private final boolean disabledAllPlannerRules; - @Nonnull private final Set disabledPlannerRewriteRules; private final boolean planRightDeep; - @Nonnull private final VectorIndexEnginePreference vectorIndexEnginePreference; - @Nonnull private final RecordQueryPlannerConfiguration recordQueryPlannerConfiguration; private final int memoizedHash; - private PlannerConfiguration(@Nonnull final Optional> readableIndexes, - @Nonnull final IndexFetchMethod indexFetchMethod, - @Nonnull final Set disabledPlannerRewriteRules, + private PlannerConfiguration(final Optional> readableIndexes, + final IndexFetchMethod indexFetchMethod, + final Set disabledPlannerRewriteRules, boolean disabledAllPlannerRules, boolean planRightDeep, - @Nonnull final VectorIndexEnginePreference vectorIndexEnginePreference) { + final VectorIndexEnginePreference vectorIndexEnginePreference) { this.readableIndexes = readableIndexes; this.indexFetchMethod = indexFetchMethod; this.disabledAllPlannerRules = disabledAllPlannerRules; @@ -89,12 +82,10 @@ private PlannerConfiguration(@Nonnull final Optional> readableIndexe this.recordQueryPlannerConfiguration = buildRecordQueryPlannerConfiguration(); } - @Nonnull public Optional> getReadableIndexes() { return readableIndexes; } - @Nonnull public RecordQueryPlannerConfiguration getRecordQueryPlannerConfiguration() { return recordQueryPlannerConfiguration; } @@ -119,7 +110,6 @@ public RecordQueryPlannerConfiguration getRecordQueryPlannerConfiguration() { * @return {@code this} if the flag is already equal to {@code newPlanRightDeep}, * otherwise a new {@link PlannerConfiguration} with the flag overridden */ - @Nonnull public PlannerConfiguration withPlanRightDeep(final boolean newPlanRightDeep) { if (this.planRightDeep == newPlanRightDeep) { return this; @@ -154,7 +144,6 @@ public int hashCode() { return memoizedHash; } - @Nonnull private RecordQueryPlannerConfiguration buildRecordQueryPlannerConfiguration() { final var configurationBuilder = RecordQueryPlannerConfiguration.builder() .setIndexScanPreference(QueryPlanner.IndexScanPreference.PREFER_INDEX) @@ -169,22 +158,19 @@ private RecordQueryPlannerConfiguration buildRecordQueryPlannerConfiguration() { return configurationBuilder.build(); } - @Nonnull - public static PlannerConfiguration of(@Nonnull final Optional> readableIndexesMaybe, - @Nonnull final Options options) { + public static PlannerConfiguration of(final Optional> readableIndexesMaybe, + final Options options) { final var disabledPlannerRules = ImmutableSet.copyOf(options.>getOption(Options.Name.DISABLED_PLANNER_RULES)); return new PlannerConfiguration(readableIndexesMaybe, OptionsUtils.getIndexFetchMethod(options), disabledPlannerRules, options.getOption(DISABLE_PLANNER_REWRITING), options.getOption(PLAN_RIGHT_DEEP), OptionsUtils.getVectorIndexEnginePreference(options)); } - @Nonnull public static PlannerConfiguration ofAllAvailableIndexes() { return of(Optional.empty(), Options.none()); } - @Nonnull - public static PlannerConfiguration ofAllAvailableIndexes(@Nonnull final Options options) { + public static PlannerConfiguration ofAllAvailableIndexes(final Options options) { return of(Optional.empty(), options); } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PreparedParams.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PreparedParams.java index 3b31aba9699..a837f22e84a 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PreparedParams.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PreparedParams.java @@ -26,9 +26,7 @@ import com.apple.foundationdb.relational.util.Assert; import com.google.common.collect.ImmutableMap; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.Map; /** @@ -38,25 +36,22 @@ @API(API.Status.EXPERIMENTAL) public final class PreparedParams { - @Nonnull private static final PreparedParams EMPTY_PARAMETERS = new PreparedParams(Map.of(), Map.of()); - @Nonnull private final Map unnamedParams; - @Nonnull private final Map namedParams; private int nextParam = 1; - private PreparedParams(@Nonnull Map unnamedParams, - @Nonnull Map namedParameters) { + private PreparedParams(Map unnamedParams, + Map namedParameters) { this.unnamedParams = unnamedParams; this.namedParams = namedParameters; } - private PreparedParams(@Nonnull Map unnamedParams, - @Nonnull Map namedParameters, + private PreparedParams(Map unnamedParams, + Map namedParameters, int nextParam) { this.unnamedParams = unnamedParams; this.namedParams = namedParameters; @@ -76,7 +71,7 @@ public Object nextUnnamedParamValue() { } @Nullable - public Object namedParamValue(@Nonnull String name) { + public Object namedParamValue(String name) { Assert.thatUnchecked(namedParams.containsKey(name), ErrorCode.UNDEFINED_PARAMETER, "No value found for parameter " + name ); @@ -87,34 +82,28 @@ public boolean isEmpty() { return this.namedParams.isEmpty() && this.unnamedParams.isEmpty(); } - @Nonnull public static PreparedParams empty() { return EMPTY_PARAMETERS; } - @Nonnull - public static PreparedParams of(@Nonnull Map parameters, - @Nonnull Map namedParameters) { + public static PreparedParams of(Map parameters, + Map namedParameters) { return new PreparedParams(parameters, namedParameters); } - @Nonnull - public static PreparedParams ofUnnamed(@Nonnull Map parameters) { + public static PreparedParams ofUnnamed(Map parameters) { return of(parameters, ImmutableMap.of()); } - @Nonnull - public static PreparedParams ofNamed(@Nonnull Map parameters) { + public static PreparedParams ofNamed(Map parameters) { return new PreparedParams(ImmutableMap.of(), parameters); } - @Nonnull - public static PreparedParams copyOf(@Nonnull PreparedParams other) { + public static PreparedParams copyOf(PreparedParams other) { return copyOf(other, false); } - @Nonnull - public static PreparedParams copyOf(@Nonnull PreparedParams other, boolean withCurrentUnnamedParamIndex) { + public static PreparedParams copyOf(PreparedParams other, boolean withCurrentUnnamedParamIndex) { if (withCurrentUnnamedParamIndex) { return new PreparedParams(other.unnamedParams, other.namedParams, other.currentUnnamedParamIndex()); } else { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ProceduralPlan.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ProceduralPlan.java index f0465ba52dd..f4109aba8c0 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ProceduralPlan.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ProceduralPlan.java @@ -28,8 +28,6 @@ import com.apple.foundationdb.relational.api.ddl.ConstantAction; import com.apple.foundationdb.relational.api.exceptions.RelationalException; import com.apple.foundationdb.relational.api.metrics.RelationalMetric; - -import javax.annotation.Nonnull; import java.util.Objects; @API(API.Status.EXPERIMENTAL) @@ -37,7 +35,7 @@ public final class ProceduralPlan extends Plan { private final ConstantAction action; - private ProceduralPlan(@Nonnull final ConstantAction action) { + private ProceduralPlan(final ConstantAction action) { super("ProceduralPlan(" + action.getClass().getSimpleName() + ")"); this.action = action; } @@ -48,13 +46,13 @@ public boolean isUpdatePlan() { } @Override - public Plan optimize(@Nonnull CascadesPlanner planner, @Nonnull PlanContext planContext, - @Nonnull PlanHashable.PlanHashMode currentPlanHashMode) { + public Plan optimize(CascadesPlanner planner, PlanContext planContext, + PlanHashable.PlanHashMode currentPlanHashMode) { return this; } @Override - public Void executeInternal(@Nonnull final ExecutionContext context) throws RelationalException { + public Void executeInternal(final ExecutionContext context) throws RelationalException { final var metricCollector = Objects.requireNonNull(context.metricCollector); return metricCollector.clock(RelationalMetric.RelationalEvent.EXECUTE_PROCEDURAL_PLAN_ACTION, () -> { action.executeAction(context.transaction); @@ -62,19 +60,16 @@ public Void executeInternal(@Nonnull final ExecutionContext context) throws Rela }); } - @Nonnull @Override public QueryPlanConstraint getConstraint() { return QueryPlanConstraint.noConstraint(); } - @Nonnull @Override - public Plan withExecutionContext(@Nonnull final QueryExecutionContext queryExecutionContext) { + public Plan withExecutionContext(final QueryExecutionContext queryExecutionContext) { return this; } - @Nonnull @Override public String explain() { // TODO: this implementation is not correct as a few actions don't implement toString @@ -82,7 +77,7 @@ public String explain() { return "ProceduralPlan(" + action + ")"; } - public static ProceduralPlan of(@Nonnull final ConstantAction action) { + public static ProceduralPlan of(final ConstantAction action) { return new ProceduralPlan(action); } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryExecutionContext.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryExecutionContext.java index 616b6d68577..58aaf71bb01 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryExecutionContext.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryExecutionContext.java @@ -25,14 +25,11 @@ import com.apple.foundationdb.record.PlanHashable; import com.apple.foundationdb.record.query.plan.cascades.Quantifier; import com.apple.foundationdb.record.query.plan.cascades.typing.TypeRepository; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; public interface QueryExecutionContext { - @Nonnull - default EvaluationContext getEvaluationContext(@Nonnull TypeRepository typeRepository) { + default EvaluationContext getEvaluationContext(TypeRepository typeRepository) { final var literals = getLiterals(); if (literals.isEmpty()) { return EvaluationContext.forTypeRepository(typeRepository); @@ -42,12 +39,10 @@ default EvaluationContext getEvaluationContext(@Nonnull TypeRepository typeRepos return builder.build(typeRepository); } - @Nonnull default EvaluationContext getEvaluationContext() { return getEvaluationContext(ParseHelpers.EMPTY_TYPE_REPOSITORY); } - @Nonnull ExecuteProperties.Builder getExecutionPropertiesBuilder(); @Nullable @@ -55,11 +50,9 @@ default EvaluationContext getEvaluationContext() { int getParameterHash(); - @Nonnull Literals getLiterals(); boolean isForExplain(); // todo (yhatem) remove. - @Nonnull PlanHashable.PlanHashMode getPlanHashMode(); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryParser.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryParser.java index 9ed9fb64b2a..a7023e46790 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryParser.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryParser.java @@ -44,8 +44,6 @@ import org.antlr.v4.runtime.dfa.DFA; import org.antlr.v4.runtime.misc.Interval; import org.antlr.v4.runtime.tree.ParseTree; - -import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.BitSet; import java.util.List; @@ -61,10 +59,8 @@ public class QueryParser { @VisibleForTesting public static class ErrorStringifier extends BaseErrorListener { - @Nonnull private final List syntaxErrors; - @Nonnull private final List ambiguityErrors; @VisibleForTesting @@ -73,12 +69,10 @@ public ErrorStringifier() { ambiguityErrors = new ArrayList<>(); } - @Nonnull List getSyntaxErrors() { return syntaxErrors; } - @Nonnull List getAmbiguityErrors() { return ambiguityErrors; } @@ -103,7 +97,7 @@ public void reportAmbiguity(Parser recognizer, recognizer.getInputStream().getText(Interval.of(startIndex, recognizer.getInputStream().size() - 1)), exact)); } - static T withParseErrorHandling(@Nonnull final Function parsingRoutine) throws RelationalException { + static T withParseErrorHandling(final Function parsingRoutine) throws RelationalException { final var listener = new ErrorStringifier(); final var result = parsingRoutine.apply(listener); if (Environment.isDebug() && !listener.getAmbiguityErrors().isEmpty()) { @@ -122,8 +116,7 @@ static T withParseErrorHandling(@Nonnull final Function } } - @Nonnull - public static ParseTreeInfoImpl parse(@Nonnull final String query) throws RelationalException { + public static ParseTreeInfoImpl parse(final String query) throws RelationalException { final var tokenSource = new RelationalLexer(new CaseInsensitiveCharStream(query)); final var parser = getParserInstance(new CommonTokenStream(tokenSource)); @@ -136,9 +129,8 @@ public static ParseTreeInfoImpl parse(@Nonnull final String query) throws Relati return ParseTreeInfoImpl.from(rootContext); } - @Nonnull - private static

P parse(@Nonnull final String query, @Nonnull final Consumer tokenConsumer, - @Nonnull final Function parse) { + private static

P parse(final String query, final Consumer tokenConsumer, + final Function parse) { final var tokenSource = new RelationalLexer(new CaseInsensitiveCharStream(query)); final var tokensStream = new CommonTokenStream(tokenSource); tokenConsumer.accept(tokensStream); @@ -156,8 +148,7 @@ private static

P parse(@Nonnull final String query, @Nonnull final Consumer< } - @Nonnull - public static RelationalParser.SqlInvokedFunctionContext parseFunction(@Nonnull final String functionString) { + public static RelationalParser.SqlInvokedFunctionContext parseFunction(final String functionString) { // the routine here is assumed to start with CREATE, // however due to how the parser rules are structured, // parsing invoked function starts immediately after CREATE @@ -165,8 +156,7 @@ public static RelationalParser.SqlInvokedFunctionContext parseFunction(@Nonnull return parse(functionString, BufferedTokenStream::consume, RelationalParser::sqlInvokedFunction); } - @Nonnull - public static RelationalParser.QueryContext parseView(@Nonnull final String viewDefinition) { + public static RelationalParser.QueryContext parseView(final String viewDefinition) { return parse(viewDefinition, ignored -> { } , RelationalParser::query); } @@ -182,13 +172,12 @@ public Void visitPreparedStatementParameter(final RelationalParser.PreparedState * visits the parse tree and throws if it encounters a prepared parameter. * @param context The parse tree of the query. */ - public static void validateNoPreparedParams(@Nonnull final ParseTree context) { + public static void validateNoPreparedParams(final ParseTree context) { final var validator = new PreparedParamsValidator(); validator.visit(context); } - @Nonnull - private static RelationalParser getParserInstance(@Nonnull final TokenStream tokenStream) { + private static RelationalParser getParserInstance(final TokenStream tokenStream) { final var parser = new RelationalParser(tokenStream); if (Environment.isDebug()) { parser.getInterpreter().setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryPlan.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryPlan.java index 2f2903a1f28..95bae5fa059 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryPlan.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryPlan.java @@ -85,9 +85,7 @@ import com.google.common.collect.ImmutableList; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.Message; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.sql.SQLException; import java.sql.Struct; import java.util.ArrayList; @@ -104,51 +102,44 @@ public abstract class QueryPlan extends Plan implements Typed { - protected QueryPlan(@Nonnull final String query) { + protected QueryPlan(final String query) { super(query); } public static class PhysicalQueryPlan extends QueryPlan { - @Nonnull private final RecordQueryPlan recordQueryPlan; @Nullable private final PlannerEventStatsMaps plannerEventStatsMaps; - @Nonnull private final PlanHashMode currentPlanHashMode; private final Supplier planHashSupplier; - @Nonnull private final TypeRepository typeRepository; - @Nonnull private final QueryPlanConstraint constraint; - @Nonnull private final QueryPlanConstraint continuationConstraint; - @Nonnull private final QueryExecutionContext queryExecutionContext; /** * Semantic type structure captured during semantic analysis. * Complete StructType with field names and nested struct type names preserved. */ - @Nonnull private final DataType.StructType semanticStructType; - public PhysicalQueryPlan(@Nonnull final RecordQueryPlan recordQueryPlan, + public PhysicalQueryPlan(final RecordQueryPlan recordQueryPlan, @Nullable final PlannerEventStatsMaps plannerEventStatsMaps, - @Nonnull final TypeRepository typeRepository, - @Nonnull final QueryPlanConstraint constraint, - @Nonnull final QueryPlanConstraint continuationConstraint, - @Nonnull final QueryExecutionContext queryExecutionContext, - @Nonnull final String query, - @Nonnull final PlanHashMode currentPlanHashMode, - @Nonnull final DataType.StructType semanticStructType) { + final TypeRepository typeRepository, + final QueryPlanConstraint constraint, + final QueryPlanConstraint continuationConstraint, + final QueryExecutionContext queryExecutionContext, + final String query, + final PlanHashMode currentPlanHashMode, + final DataType.StructType semanticStructType) { super(query); this.recordQueryPlan = recordQueryPlan; this.plannerEventStatsMaps = plannerEventStatsMaps; @@ -161,47 +152,39 @@ public PhysicalQueryPlan(@Nonnull final RecordQueryPlan recordQueryPlan, this.semanticStructType = semanticStructType; } - @Nonnull public RecordQueryPlan getRecordQueryPlan() { return recordQueryPlan; } - @Nonnull public TypeRepository getTypeRepository() { return typeRepository; } @Override - @Nonnull public QueryPlanConstraint getConstraint() { return constraint; } - @Nonnull public QueryPlanConstraint getContinuationConstraint() { return continuationConstraint; } - @Nonnull @Override public Type getResultType() { return Assert.notNullUnchecked(recordQueryPlan.getResultType().getInnerType()); } - @Nonnull public QueryExecutionContext getQueryExecutionContext() { return queryExecutionContext; } - @Nonnull public PlanHashMode getCurrentPlanHashMode() { return currentPlanHashMode; } @SuppressWarnings("PMD.CompareObjectsWithEquals") @Override - @Nonnull - public PhysicalQueryPlan withExecutionContext(@Nonnull final QueryExecutionContext queryExecutionContext) { + public PhysicalQueryPlan withExecutionContext(final QueryExecutionContext queryExecutionContext) { if (queryExecutionContext == this.queryExecutionContext) { return this; } @@ -210,7 +193,6 @@ public PhysicalQueryPlan withExecutionContext(@Nonnull final QueryExecutionConte semanticStructType); } - @Nonnull @Override public String explain() { final var executeProperties = queryExecutionContext.getExecutionPropertiesBuilder(); @@ -238,15 +220,15 @@ public boolean isUpdatePlan() { } @Override - public Plan optimize(@Nonnull CascadesPlanner planner, - @Nonnull PlanContext planContext, - @Nonnull PlanHashMode currentPlanHashMode) { + public Plan optimize(CascadesPlanner planner, + PlanContext planContext, + PlanHashMode currentPlanHashMode) { return this; } @Override @SuppressWarnings("PMD.CloseResource") // Connection not owned by this method - public RelationalResultSet executeInternal(@Nonnull final ExecutionContext executionContext) throws RelationalException { + public RelationalResultSet executeInternal(final ExecutionContext executionContext) throws RelationalException { if (!(executionContext.connection instanceof EmbeddedRelationalConnection)) { //this is required until TODO is resolved throw new RelationalException("Cannot execute a QueryPlan without an EmbeddedRelationalConnection", ErrorCode.INTERNAL_ERROR); @@ -276,10 +258,10 @@ public RelationalResultSet executeInternal(@Nonnull final ExecutionContext execu } } - protected void validatePlanAgainstEnvironment(@Nonnull final ContinuationImpl parsedContinuation, - @Nonnull final FDBRecordStoreBase fdbRecordStore, - @Nonnull final ExecutionContext executionContext, - @Nonnull final Set validPlanHashModes) throws RelationalException { + protected void validatePlanAgainstEnvironment(final ContinuationImpl parsedContinuation, + final FDBRecordStoreBase fdbRecordStore, + final ExecutionContext executionContext, + final Set validPlanHashModes) throws RelationalException { PlanValidator.validateHashes(parsedContinuation, executionContext.metricCollector, recordQueryPlan, queryExecutionContext, currentPlanHashMode, validPlanHashModes); @@ -292,9 +274,8 @@ protected void validatePlanAgainstEnvironment(@Nonnull final } } - @Nonnull - protected Optional getSerializedPlanFromContinuation(@Nonnull ContinuationImpl parsedContinuation, - @Nonnull ExecutionContext executionContext) throws RelationalException { + protected Optional getSerializedPlanFromContinuation(ContinuationImpl parsedContinuation, + ExecutionContext executionContext) throws RelationalException { final var compiledStatement = parsedContinuation.getCompiledStatement(); if (compiledStatement == null || !compiledStatement.hasPlan() || !compiledStatement.hasPlanSerializationMode()) { return Optional.empty(); @@ -315,8 +296,7 @@ protected Optional getSerializedPlanFromContinuation(@Nonnull C } } - @Nonnull - private RelationalResultSet executeExplain(@Nonnull ContinuationImpl parsedContinuation, + private RelationalResultSet executeExplain(ContinuationImpl parsedContinuation, ExecutionContext executionContext) throws RelationalException { final var continuationStructType = DataType.StructType.from( "PLAN_CONTINUATION", List.of( @@ -413,12 +393,11 @@ private RelationalResultSet executeExplain(@Nonnull ContinuationImpl parsedConti plannerMetrics)).iterator(), 0); } - @Nonnull @SuppressWarnings("PMD.CloseResource") // cursor returned inside the ResultSet, Connection now owned by this method - private RelationalResultSet executePhysicalPlan(@Nonnull final RecordLayerSchema recordLayerSchema, - @Nonnull final EvaluationContext evaluationContext, - @Nonnull final ExecutionContext executionContext, - @Nonnull final ContinuationImpl parsedContinuation) throws RelationalException { + private RelationalResultSet executePhysicalPlan(final RecordLayerSchema recordLayerSchema, + final EvaluationContext evaluationContext, + final ExecutionContext executionContext, + final ContinuationImpl parsedContinuation) throws RelationalException { final var connection = (EmbeddedRelationalConnection) executionContext.connection; Type type = recordQueryPlan.getResultType().getInnerType(); Assert.notNull(type); @@ -448,10 +427,9 @@ private RelationalResultSet executePhysicalPlan(@Nonnull final RecordLayerSchema }); } - @Nonnull - private Continuation enrichContinuation(@Nonnull final Continuation continuation, - @Nonnull final PlanHashMode currentPlanHashMode, - @Nonnull final Continuation.Reason reason) throws RelationalException { + private Continuation enrichContinuation(final Continuation continuation, + final PlanHashMode currentPlanHashMode, + final Continuation.Reason reason) throws RelationalException { final var continuationBuilder = ContinuationImpl.copyOf(continuation).asBuilder() .withBindingHash(queryExecutionContext.getParameterHash()) .withPlanHash(planHashSupplier.get()) @@ -492,34 +470,31 @@ private Continuation enrichContinuation(@Nonnull final Continuation continuation return continuationBuilder.build(); } - public int planHash(@Nonnull final PlanHashMode currentPlanHashMode) { + public int planHash(final PlanHashMode currentPlanHashMode) { return recordQueryPlan.planHash(currentPlanHashMode); } } public static class ContinuedPhysicalQueryPlan extends PhysicalQueryPlan { - @Nonnull private final PlanHashMode serializedPlanHashMode; - @Nonnull private final Supplier serializedPlanHashSupplier; - public ContinuedPhysicalQueryPlan(@Nonnull final RecordQueryPlan recordQueryPlan, - @Nonnull final TypeRepository typeRepository, - @Nonnull final QueryPlanConstraint continuationConstraint, - @Nonnull final QueryExecutionContext queryExecutionParameters, - @Nonnull final String query, - @Nonnull final PlanHashMode currentPlanHashMode, - @Nonnull final PlanHashMode serializedPlanHashMode, - @Nonnull final DataType.StructType semanticStructType) { + public ContinuedPhysicalQueryPlan(final RecordQueryPlan recordQueryPlan, + final TypeRepository typeRepository, + final QueryPlanConstraint continuationConstraint, + final QueryExecutionContext queryExecutionParameters, + final String query, + final PlanHashMode currentPlanHashMode, + final PlanHashMode serializedPlanHashMode, + final DataType.StructType semanticStructType) { super(recordQueryPlan, null, typeRepository, QueryPlanConstraint.noConstraint(), continuationConstraint, queryExecutionParameters, query, currentPlanHashMode, semanticStructType); this.serializedPlanHashMode = serializedPlanHashMode; this.serializedPlanHashSupplier = Suppliers.memoize(() -> recordQueryPlan.planHash(serializedPlanHashMode)); } - @Nonnull public PlanHashMode getSerializedPlanHashMode() { return serializedPlanHashMode; } @@ -542,18 +517,17 @@ public PlanHashMode getSerializedPlanHashMode() { * @return This instance (since continuation plans are never cached) */ @Override - @Nonnull - public PhysicalQueryPlan withExecutionContext(@Nonnull final QueryExecutionContext queryExecutionContext) { + public PhysicalQueryPlan withExecutionContext(final QueryExecutionContext queryExecutionContext) { // This method is never called in production - continuation plans bypass the cache. // Return this to avoid maintaining dead code. return this; } @Override - protected void validatePlanAgainstEnvironment(@Nonnull final ContinuationImpl parsedContinuation, - @Nonnull final FDBRecordStoreBase fdbRecordStore, - @Nonnull final ExecutionContext executionContext, - @Nonnull final Set validPlanHashModes) throws RelationalException { + protected void validatePlanAgainstEnvironment(final ContinuationImpl parsedContinuation, + final FDBRecordStoreBase fdbRecordStore, + final ExecutionContext executionContext, + final Set validPlanHashModes) throws RelationalException { // We cannot be at the beginning Verify.verify(!parsedContinuation.atBeginning()); @@ -573,9 +547,8 @@ protected void validatePlanAgainstEnvironment(@Nonnull final } @Override - @Nonnull - protected Optional getSerializedPlanFromContinuation(@Nonnull ContinuationImpl parsedContinuation, - @Nonnull ExecutionContext executionContext) throws RelationalException { + protected Optional getSerializedPlanFromContinuation(ContinuationImpl parsedContinuation, + ExecutionContext executionContext) throws RelationalException { Assert.that( Objects.requireNonNull(parsedContinuation.getPlanHash()).equals(serializedPlanHashSupplier.get()), ErrorCode.INTERNAL_ERROR, @@ -590,30 +563,25 @@ protected Optional getSerializedPlanFromContinuation(@Nonnull C */ public static class LogicalQueryPlan extends QueryPlan { - @Nonnull private final RelationalExpression relationalExpression; - @Nonnull private final MutablePlanGenerationContext context; - @Nonnull private final String query; /** * Semantic type structure captured during semantic analysis. * Preserves struct type names - will be merged with planner field names after planning. */ - @Nonnull private final DataType.StructType semanticStructType; @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - @Nonnull private Optional optimizedPlan; - private LogicalQueryPlan(@Nonnull final RelationalExpression relationalExpression, - @Nonnull final MutablePlanGenerationContext context, - @Nonnull final String query, - @Nonnull final DataType.StructType semanticStructType) { + private LogicalQueryPlan(final RelationalExpression relationalExpression, + final MutablePlanGenerationContext context, + final String query, + final DataType.StructType semanticStructType) { super(query); this.relationalExpression = relationalExpression; this.context = context; @@ -629,9 +597,8 @@ public boolean isUpdatePlan() { } @Override - @Nonnull - public PhysicalQueryPlan optimize(@Nonnull CascadesPlanner planner, @Nonnull PlanContext planContext, - @Nonnull PlanHashMode currentPlanHashMode) throws RelationalException { + public PhysicalQueryPlan optimize(CascadesPlanner planner, PlanContext planContext, + PlanHashMode currentPlanHashMode) throws RelationalException { if (optimizedPlan.isPresent()) { return optimizedPlan.get(); } @@ -674,19 +641,16 @@ public PhysicalQueryPlan optimize(@Nonnull CascadesPlanner planner, @Nonnull Pla }); } - @Nonnull @Override public QueryPlanConstraint getConstraint() { return context.getPlanConstraintsForLiteralReferences(); } - @Nonnull @Override - public Plan withExecutionContext(@Nonnull final QueryExecutionContext queryExecutionContext) { + public Plan withExecutionContext(final QueryExecutionContext queryExecutionContext) { return this; } - @Nonnull @Override public String explain() { // TODO: We should return something meaningful if `optimize` wasn't called @@ -695,17 +659,15 @@ public String explain() { } @Override - public RelationalResultSet executeInternal(@Nonnull final ExecutionContext executionContext) throws RelationalException { + public RelationalResultSet executeInternal(final ExecutionContext executionContext) throws RelationalException { return this.optimizedPlan.get().execute(executionContext); } - @Nonnull @Override public Type getResultType() { return relationalExpression.getResultType(); } - @Nonnull public RelationalExpression getRelationalExpression() { return relationalExpression; } @@ -714,17 +676,15 @@ public MutablePlanGenerationContext getGenerationContext() { return context; } - @Nonnull - public static LogicalQueryPlan of(@Nonnull final RelationalExpression relationalExpression, - @Nonnull final MutablePlanGenerationContext context, - @Nonnull final String query, - @Nonnull final DataType.StructType semanticStructType) { + public static LogicalQueryPlan of(final RelationalExpression relationalExpression, + final MutablePlanGenerationContext context, + final String query, + final DataType.StructType semanticStructType) { return new LogicalQueryPlan(relationalExpression, context, query, semanticStructType); } - @Nonnull - private static QueryPlanConstraint computeContinuationPlanConstraint(@Nonnull final RecordMetaData recordMetaData, - @Nonnull final RecordQueryPlan plannedPlan) { + private static QueryPlanConstraint computeContinuationPlanConstraint(final RecordMetaData recordMetaData, + final RecordQueryPlan plannedPlan) { // this plan was planned -- we need to compute the plan constraints final var compatibleTypeEvolutionPredicate = CompatibleTypeEvolutionPredicate.fromPlan(plannedPlan); @@ -737,17 +697,15 @@ private static QueryPlanConstraint computeContinuationPlanConstraint(@Nonnull fi public static class MetadataQueryPlan extends QueryPlan { - @Nonnull private final CheckedFunctional query; - @Nonnull private final Type rowType; private interface CheckedFunctional { R apply(T t) throws RelationalException; } - private MetadataQueryPlan(@Nonnull final CheckedFunctional query, @Nonnull final Type rowType) { + private MetadataQueryPlan(final CheckedFunctional query, final Type rowType) { // TODO: TODO (Implement MetadataQueryPlan.explain) (should cover toString as well). super("MetadataQueryPlan"); this.query = query; @@ -760,43 +718,38 @@ public boolean isUpdatePlan() { } @Override - public Plan optimize(@Nonnull CascadesPlanner planner, - @Nonnull PlanContext planContext, - @Nonnull PlanHashMode currentPlanHashMode) { + public Plan optimize(CascadesPlanner planner, + PlanContext planContext, + PlanHashMode currentPlanHashMode) { return this; } @Override - public RelationalResultSet executeInternal(@Nonnull final ExecutionContext context) throws RelationalException { + public RelationalResultSet executeInternal(final ExecutionContext context) throws RelationalException { return query.apply(context.transaction); } - @Nonnull @Override public QueryPlanConstraint getConstraint() { return QueryPlanConstraint.noConstraint(); } - @Nonnull @Override - public Plan withExecutionContext(@Nonnull QueryExecutionContext queryExecutionContext) { + public Plan withExecutionContext(QueryExecutionContext queryExecutionContext) { return this; } - @Nonnull @Override public String explain() { // TODO: TODO (Implement MetadataQueryPlan.explain) return "MetadataQueryPlan"; } - @Nonnull @Override public Type getResultType() { return rowType; } - @Nonnull public static MetadataQueryPlan of(DdlQuery ddlQuery) { return new MetadataQueryPlan(ddlQuery::executeAction, ddlQuery.getResultSetMetadata()); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java index f223c093c89..508b9d28586 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java @@ -75,9 +75,7 @@ import com.google.protobuf.ByteString; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.tree.ParseTree; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.net.URI; import java.util.List; import java.util.Locale; @@ -91,6 +89,8 @@ import java.util.stream.Collectors; import java.util.stream.StreamSupport; +import static com.apple.foundationdb.relational.generated.RelationalParser.PrimitiveTypeContext; + /** * This class is responsible for performing a number of tasks revolving around semantic checks and resolution. For example, * it assists in looking up an {@link Identifier} within a chain of {@link LogicalPlanFragment}(s), expanding a {@link Star} @@ -107,20 +107,17 @@ public class SemanticAnalyzer { private static final Set BITMAP_SCALAR_FUNCTIONS = ImmutableSet.of("bitmap_bucket_offset", "bitmap_bit_position"); - @Nonnull private final SchemaTemplate metadataCatalog; - @Nonnull private final SqlFunctionCatalog functionCatalog; - @Nonnull private final MutablePlanGenerationContext mutablePlanGenerationContext; private final boolean isCaseSensitive; - public SemanticAnalyzer(@Nonnull SchemaTemplate metadataCatalog, - @Nonnull SqlFunctionCatalog functionCatalog, - @Nonnull MutablePlanGenerationContext mutablePlanGenerationContext, + public SemanticAnalyzer(SchemaTemplate metadataCatalog, + SqlFunctionCatalog functionCatalog, + MutablePlanGenerationContext mutablePlanGenerationContext, boolean isCaseSensitive) { this.metadataCatalog = metadataCatalog; this.functionCatalog = functionCatalog; @@ -155,7 +152,7 @@ public static String normalizeString(@Nullable final String string, boolean case * @param quotationMark The quotation mark to look for * @return true is the string is quoted, otherwise false. */ - private static boolean isQuoted(@Nonnull final String str, @Nonnull final String quotationMark) { + private static boolean isQuoted(final String str, final String quotationMark) { return str.startsWith(quotationMark) && str.endsWith(quotationMark); } @@ -165,9 +162,8 @@ private static boolean isQuoted(@Nonnull final String str, @Nonnull final String * @param logicalPlanFragment The plan fragments chain. * @return Optional with {@link LogicalOperator} whose name matches the given identifier, if found. */ - @Nonnull - public Optional findCteMaybe(@Nonnull final Identifier identifier, - @Nonnull final LogicalPlanFragment logicalPlanFragment) { + public Optional findCteMaybe(final Identifier identifier, + final LogicalPlanFragment logicalPlanFragment) { var currentFragment = Optional.of(logicalPlanFragment); while (currentFragment.isPresent()) { final var logicalOperators = currentFragment.get().getLogicalOperators(); @@ -183,7 +179,7 @@ public Optional findCteMaybe(@Nonnull final Identifier identifi return Optional.empty(); } - public boolean tableExists(@Nonnull final Identifier tableIdentifier) { + public boolean tableExists(final Identifier tableIdentifier) { if (tableIdentifier.getQualifier().size() > 1) { return false; } @@ -203,7 +199,7 @@ public boolean tableExists(@Nonnull final Identifier tableIdentifier) { } } - public boolean viewExists(@Nonnull final Identifier viewIdentifier) { + public boolean viewExists(final Identifier viewIdentifier) { if (viewIdentifier.getQualifier().size() > 1) { return false; } @@ -223,17 +219,15 @@ public boolean viewExists(@Nonnull final Identifier viewIdentifier) { } } - public boolean functionExists(@Nonnull final Identifier functionIdentifier) { + public boolean functionExists(final Identifier functionIdentifier) { return functionCatalog.containsFunction(functionIdentifier.getName()); } - @Nonnull public SchemaTemplate getMetadataCatalog() { return metadataCatalog; } - @Nonnull - public Table getTable(@Nonnull Identifier tableIdentifier) { + public Table getTable(Identifier tableIdentifier) { Assert.thatUnchecked(tableIdentifier.getQualifier().size() <= 1, ErrorCode.INTERNAL_ERROR, () -> String.format(Locale.ROOT, "Unknown table %s", tableIdentifier)); if (tableIdentifier.isQualified()) { final var qualifier = tableIdentifier.getQualifier().get(0); @@ -249,12 +243,12 @@ public Table getTable(@Nonnull Identifier tableIdentifier) { } } - public void validateIndexes(@Nonnull Identifier tableIdentifier, @Nonnull Set requestedIndexes) { + public void validateIndexes(Identifier tableIdentifier, Set requestedIndexes) { final var table = getTable(tableIdentifier); validateIndexes(table, requestedIndexes); } - public void validateIndexes(@Nonnull Table table, @Nonnull Set requestedIndexes) { + public void validateIndexes(Table table, Set requestedIndexes) { if (requestedIndexes.isEmpty()) { return; } @@ -266,7 +260,7 @@ public void validateIndexes(@Nonnull Table table, @Nonnull Set reque Assert.thatUnchecked(unrecognizedIndexes.isEmpty(), ErrorCode.UNDEFINED_INDEX, () -> String.format(Locale.ROOT, "Unknown index(es) %s", String.join(",", unrecognizedIndexes))); } - public void validateOrderByColumns(@Nonnull Iterable orderBys) { + public void validateOrderByColumns(Iterable orderBys) { final var duplicates = StreamSupport.stream(orderBys.spliterator(), false) .map(OrderByExpression::getExpression) .flatMap(expr -> expr.getName().stream()) @@ -281,7 +275,6 @@ public void validateOrderByColumns(@Nonnull Iterable orderBys duplicates.stream().map(Identifier::toString).collect(Collectors.joining(",")))); } - @Nonnull public Set getAllTableStorageNames() { try { return metadataCatalog.getTables().stream() @@ -293,9 +286,8 @@ public Set getAllTableStorageNames() { } } - @Nonnull - public Expression resolveCorrelatedIdentifier(@Nonnull Identifier identifier, - @Nonnull LogicalOperators operators) { + public Expression resolveCorrelatedIdentifier(Identifier identifier, + LogicalOperators operators) { Assert.thatUnchecked(identifier.isQualified(), ErrorCode.UNDEFINED_TABLE, () -> String.format(Locale.ROOT, "Unknown table %s", identifier)); return resolveIdentifier(identifier, operators); } @@ -313,9 +305,8 @@ public Expression resolveCorrelatedIdentifier(@Nonnull Identifier identifier, * * @return a {@link Star} expression capturing the expansion */ - @Nonnull - public Star expandStar(@Nonnull Optional optionalQualifier, - @Nonnull LogicalOperators operators) { + public Star expandStar(Optional optionalQualifier, + LogicalOperators operators) { final var forEachOperators = operators.forEachOnly(); // Case 1: no qualifier, e.g. SELECT * FROM T, R; @@ -363,9 +354,8 @@ public Star expandStar(@Nonnull Optional optionalQualifier, return Star.overQuantifier(optionalQualifier, expression.getUnderlying(), qualifier.getName(), expressions); } - @Nonnull - public Expression resolveIdentifier(@Nonnull Identifier identifier, - @Nonnull LogicalPlanFragment planFragment) { + public Expression resolveIdentifier(Identifier identifier, + LogicalPlanFragment planFragment) { // Column resolution takes priority over table-row resolution across all visible fragments. // Fallback: if the identifier names a table or alias in scope, return the full row as a struct. // This makes SELECT FOO FROM FOO equivalent to SELECT (*) FROM FOO when no column named FOO exists. @@ -375,11 +365,10 @@ public Expression resolveIdentifier(@Nonnull Identifier identifier, () -> String.format(Locale.ROOT, "Attempting to query non existing column %s", identifier)); } - @Nonnull private Optional resolveAcrossFragments( - @Nonnull Identifier identifier, - @Nonnull LogicalPlanFragment planFragment, - @Nonnull BiFunction> resolver) { + Identifier identifier, + LogicalPlanFragment planFragment, + BiFunction> resolver) { // Search through all visible plan fragments: // - in each plan fragment, search operators left to right. // - if identifier is not resolved, go to parent plan fragment. @@ -396,9 +385,8 @@ private Optional resolveAcrossFragments( return Optional.empty(); } - @Nonnull - private Optional resolveAsTableRowMaybe(@Nonnull Identifier identifier, - @Nonnull LogicalOperators operators) { + private Optional resolveAsTableRowMaybe(Identifier identifier, + LogicalOperators operators) { final var identifierOptional = Optional.of(identifier); return Streams.stream(operators.forEachOnly()) .filter(op -> op.getName().equals(identifierOptional)) @@ -406,9 +394,8 @@ private Optional resolveAsTableRowMaybe(@Nonnull Identifier identifi .map(ignored -> Expression.of(expandStar(identifierOptional, operators).getUnderlying(), identifier)); } - @Nonnull - public Expression resolveIdentifier(@Nonnull Identifier identifier, - @Nonnull LogicalOperators operators) { + public Expression resolveIdentifier(Identifier identifier, + LogicalOperators operators) { var attributes = lookup(identifier, operators, true); Assert.thatUnchecked(attributes.size() <= 1, ErrorCode.AMBIGUOUS_COLUMN, () -> String.format(Locale.ROOT, "Ambiguous reference %s", identifier)); if (attributes.isEmpty()) { @@ -419,9 +406,8 @@ public Expression resolveIdentifier(@Nonnull Identifier identifier, return attributes.get(0); } - @Nonnull - private Optional resolveIdentifierMaybe(@Nonnull Identifier identifier, - @Nonnull LogicalOperators operators) { + private Optional resolveIdentifierMaybe(Identifier identifier, + LogicalOperators operators) { var attributes = lookup(identifier, operators, true); Assert.thatUnchecked(attributes.size() <= 1, ErrorCode.AMBIGUOUS_COLUMN, () -> String.format(Locale.ROOT, "Ambiguous reference %s", identifier)); if (attributes.isEmpty()) { @@ -434,9 +420,8 @@ private Optional resolveIdentifierMaybe(@Nonnull Identifier identifi return Optional.of(attributes.get(0)); } - @Nonnull - private List lookup(@Nonnull Identifier referenceIdentifier, - @Nonnull LogicalOperators operators, + private List lookup(Identifier referenceIdentifier, + LogicalOperators operators, boolean matchQualifiedOnly) { if (matchQualifiedOnly && !referenceIdentifier.isQualified()) { return ImmutableList.of(); @@ -506,9 +491,8 @@ private List lookup(@Nonnull Identifier referenceIdentifier, .build(); } - @Nonnull - public Optional lookupAlias(@Nonnull Identifier requestedAlias, - @Nonnull Expressions existingExpressions) { + public Optional lookupAlias(Identifier requestedAlias, + Expressions existingExpressions) { if (requestedAlias.isQualified()) { return Optional.empty(); } @@ -531,9 +515,9 @@ public Optional lookupAlias(@Nonnull Identifier requestedAlias, return matchedAttributes.isEmpty() ? Optional.empty() : Optional.of(matchedAttributes.get(0)); } - public Optional lookupNestedField(@Nonnull Identifier requestedIdentifier, - @Nonnull Expression existingExpression, - @Nonnull LogicalOperator logicalOperator, + public Optional lookupNestedField(Identifier requestedIdentifier, + Expression existingExpression, + LogicalOperator logicalOperator, boolean matchQualifiedOnly) { final var effectiveExistingExpr = matchQualifiedOnly && logicalOperator.getName().isPresent() ? existingExpression.withQualifier(Optional.of(logicalOperator.getName().get())) : @@ -541,10 +525,9 @@ public Optional lookupNestedField(@Nonnull Identifier requestedIdent return lookupNestedField(requestedIdentifier, existingExpression, effectiveExistingExpr, false); } - @Nonnull - public Optional lookupNestedField(@Nonnull Identifier requestedIdentifier, - @Nonnull Expression existingExpression, - @Nonnull Expression effectiveExistingExpr, + public Optional lookupNestedField(Identifier requestedIdentifier, + Expression existingExpression, + Expression effectiveExistingExpr, boolean allowLookupRoot) { // if allow look up root and the requestedIdentifier is effectiveExistingExpr, return effectiveExistingExpr if (allowLookupRoot && requestedIdentifier.fullyQualifiedName().size() == effectiveExistingExpr.getName().get().fullyQualifiedName().size()) { @@ -599,7 +582,7 @@ public Optional lookupNestedField(@Nonnull Identifier requestedIdent public static final class ParsedTypeInfo { @Nullable - private final RelationalParser.PrimitiveTypeContext primitiveTypeContext; + private final PrimitiveTypeContext primitiveTypeContext; @Nullable private final Identifier customType; @@ -608,7 +591,7 @@ public static final class ParsedTypeInfo { private final boolean isRepeated; - private ParsedTypeInfo(@Nullable final RelationalParser.PrimitiveTypeContext primitiveTypeContext, + private ParsedTypeInfo(@Nullable final PrimitiveTypeContext primitiveTypeContext, @Nullable final Identifier customType, final boolean isNullable, final boolean isRepeated) { this.primitiveTypeContext = primitiveTypeContext; this.customType = customType; @@ -621,7 +604,7 @@ public boolean hasPrimitiveType() { } @Nullable - public RelationalParser.PrimitiveTypeContext getPrimitiveTypeContext() { + public PrimitiveTypeContext getPrimitiveTypeContext() { return primitiveTypeContext; } @@ -642,21 +625,18 @@ public boolean isRepeated() { return isRepeated; } - @Nonnull - public static ParsedTypeInfo ofPrimitiveType(@Nonnull final RelationalParser.PrimitiveTypeContext primitiveTypeContext, + public static ParsedTypeInfo ofPrimitiveType(final PrimitiveTypeContext primitiveTypeContext, final boolean isNullable, final boolean isRepeated) { return new ParsedTypeInfo(primitiveTypeContext, null, isNullable, isRepeated); } - @Nonnull - public static ParsedTypeInfo ofCustomType(@Nonnull final Identifier customType, + public static ParsedTypeInfo ofCustomType(final Identifier customType, final boolean isNullable, final boolean isRepeated) { return new ParsedTypeInfo(null, customType, isNullable, isRepeated); } } - @Nonnull - public DataType lookupBuiltInType(@Nonnull final ParsedTypeInfo parsedTypeInfo) { + public DataType lookupBuiltInType(final ParsedTypeInfo parsedTypeInfo) { Assert.thatUnchecked(!parsedTypeInfo.hasCustomType(), ErrorCode.INTERNAL_ERROR, () -> "unexpected custom type " + Assert.notNullUnchecked(parsedTypeInfo.getCustomType()).getName()); return lookupType(parsedTypeInfo, typeToLookUp -> { @@ -665,9 +645,8 @@ public DataType lookupBuiltInType(@Nonnull final ParsedTypeInfo parsedTypeInfo) }); } - @Nonnull - public DataType lookupType(@Nonnull final ParsedTypeInfo parsedTypeInfo, - @Nonnull final Function> dataTypeProvider) { + public DataType lookupType(final ParsedTypeInfo parsedTypeInfo, + final Function> dataTypeProvider) { DataType type; final var isNullable = parsedTypeInfo.isNullable(); if (parsedTypeInfo.hasCustomType()) { @@ -744,8 +723,7 @@ public DataType lookupType(@Nonnull final ParsedTypeInfo parsedTypeInfo, } } - @Nonnull - private static Expressions expandStructExpression(@Nonnull Expression expression) { + private static Expressions expandStructExpression(Expression expression) { Assert.thatUnchecked(expression.getDataType().getCode() == DataType.Code.STRUCT, ErrorCode.INVALID_COLUMN_REFERENCE, () -> String.format(Locale.ROOT, "attempt to expand non-struct expression %s", expression)); final ImmutableList.Builder resultBuilder = ImmutableList.builder(); @@ -764,7 +742,7 @@ private static Expressions expandStructExpression(@Nonnull Expression expression return Expressions.of(resultBuilder.build()); } - public void validateInListItems(@Nonnull Expressions inListItems) { + public void validateInListItems(Expressions inListItems) { for (final var inListItem : inListItems) { final var resultType = inListItem.getUnderlying().getResultType(); Assert.thatUnchecked(resultType != Type.NULL, ErrorCode.WRONG_OBJECT_TYPE, "NULL values are not allowed in the IN list"); @@ -772,7 +750,7 @@ public void validateInListItems(@Nonnull Expressions inListItems) { } } - public static void validateGroupByAggregates(@Nonnull Expressions groupByExpressions) { + public static void validateGroupByAggregates(Expressions groupByExpressions) { final var nestedAggregates = groupByExpressions.stream() .filter(expression -> expression.getUnderlying() instanceof AggregateValue) .filter(agg -> agg.getUnderlying().preOrderStream().skip(1).anyMatch(c -> c instanceof StreamableAggregateValue || c instanceof IndexableAggregateValue)) @@ -792,8 +770,7 @@ public static void validateGroupByAggregates(@Nonnull Expressions groupByExpress * @return If all union legs have the same type, returns {@code Optional.empty()}, otherwise, returns a {@code Type.Record} * representing the maximum type of each column calculated pairwise. */ - @Nonnull - public static Optional validateUnionTypes(@Nonnull LogicalOperators unionLegs) { + public static Optional validateUnionTypes(LogicalOperators unionLegs) { final var distinctTypesCount = unionLegs.stream().map(exp -> exp.getOutput().expanded().size()).distinct().count(); Assert.thatUnchecked(distinctTypesCount == 1, ErrorCode.UNION_INCORRECT_COLUMN_COUNT, "UNION legs do not have the same number of columns"); @@ -820,8 +797,7 @@ public static Optional validateUnionTypes(@Nonnull LogicalOperators return requiresPromotion ? Optional.of(Assert.notNullUnchecked(result)) : Optional.empty(); } - @Nonnull - public Type.Array resolveArrayTypeFromValues(@Nonnull Expressions arrayItems) { + public Type.Array resolveArrayTypeFromValues(Expressions arrayItems) { final var arrayItemsTypes = Streams .stream(arrayItems) .map(Expression::getUnderlying) @@ -830,20 +806,20 @@ public Type.Array resolveArrayTypeFromValues(@Nonnull Expressions arrayItems) { return resolveArrayTypeFromElementTypes(arrayItemsTypes); } - public static boolean isComposableFrom(@Nonnull Expression expression, - @Nonnull Expressions parts, - @Nonnull AliasMap aliasMap, - @Nonnull Set constantCorrelations) { + public static boolean isComposableFrom(Expression expression, + Expressions parts, + AliasMap aliasMap, + Set constantCorrelations) { final Correlated.BoundEquivalence boundEquivalence = new Correlated.BoundEquivalence<>(aliasMap); final var boundParts = Streams.stream(parts).map(Expression::getUnderlying).map(boundEquivalence::wrap) .collect(ImmutableSet.toImmutableSet()); return isComposableFromInternal(expression.getUnderlying(), boundParts, boundEquivalence, constantCorrelations); } - private static boolean isComposableFromInternal(@Nonnull Value value, - @Nonnull Set> parts, - @Nonnull Correlated.BoundEquivalence boundEquivalence, - @Nonnull Set constantCorrelations) { + private static boolean isComposableFromInternal(Value value, + Set> parts, + Correlated.BoundEquivalence boundEquivalence, + Set constantCorrelations) { final var boundValue = boundEquivalence.wrap(value); if (parts.contains(boundValue)) { return true; @@ -871,8 +847,7 @@ private static boolean isComposableFromInternal(@Nonnull Value value, return false; } - @Nonnull - private static Type.Array resolveArrayTypeFromElementTypes(@Nonnull List types) { + private static Type.Array resolveArrayTypeFromElementTypes(List types) { Type elementType; if (types.isEmpty()) { elementType = Type.nullType(); @@ -889,7 +864,7 @@ private static Type.Array resolveArrayTypeFromElementTypes(@Nonnull List t * validates that a SQL {@code LIMIT} expression is within allowed limits of {@code [1, Integer.MAX_VALUE]}. * @param expression The {@code LIMIT} literal expression. */ - public static void validateLimit(@Nonnull Expression expression) { + public static void validateLimit(Expression expression) { final long minInclusive = 1; final long maxInclusive = Integer.MAX_VALUE; final var underlying = expression.getUnderlying(); @@ -912,7 +887,7 @@ public static void validateLimit(@Nonnull Expression expression) { Assert.failUnchecked("unexpected limit type " + value.getClass()); } - public static void validateDatabaseUri(@Nonnull Identifier path) { + public static void validateDatabaseUri(Identifier path) { validateDatabaseUri(path.getName()); } @@ -924,19 +899,17 @@ public static void validateDatabaseUri(String pathName) { ErrorCode.INVALID_PATH, () -> String.format(Locale.ROOT, "invalid database path '%s'", pathName)); } - public static void validateCteColumnAliases(@Nonnull LogicalOperator logicalOperator, @Nonnull List columnAliases) { + public static void validateCteColumnAliases(LogicalOperator logicalOperator, List columnAliases) { final var expressions = logicalOperator.getOutput().expanded(); Assert.thatUnchecked(expressions.size() == columnAliases.size(), ErrorCode.INVALID_COLUMN_REFERENCE, () -> String.format(Locale.ROOT, "cte query has %d column(s), however %d aliases defined", expressions.size(), columnAliases.size())); } - @Nonnull - public static NonnullPair, String> parseSchemaIdentifier(@Nonnull final Identifier schemaIdentifier) { + public static NonnullPair, String> parseSchemaIdentifier(final Identifier schemaIdentifier) { return parseSchemaURI(schemaIdentifier.getName()); } - @Nonnull - public static NonnullPair, String> parseSchemaURI(@Nonnull final String id) { + public static NonnullPair, String> parseSchemaURI(final String id) { Assert.notNullUnchecked(id); if (id.startsWith("/")) { validateDatabaseUri(id); @@ -948,7 +921,7 @@ public static NonnullPair, String> parseSchemaURI(@Nonnull final S } } - public static void validateContinuation(@Nonnull final Expression continuation) { + public static void validateContinuation(final Expression continuation) { // currently, this only validates that the underlying Value is a byte string. // in the future, we might add more context-aware checks. final var underlying = continuation.getUnderlying(); @@ -973,8 +946,7 @@ public static void validateContinuation(@Nonnull final Expression continuation) * * @return An {@link Expression} representing the resolved SQL function. */ - @Nonnull - public Expression resolveFunction(@Nonnull final String functionName, @Nonnull CallSiteArguments arguments, + public Expression resolveFunction(final String functionName, CallSiteArguments arguments, boolean flattenSingleItemRecords) { Assert.thatUnchecked(functionCatalog.containsFunction(functionName), ErrorCode.UNSUPPORTED_QUERY, () -> String.format(Locale.ROOT, "Unsupported operator %s", functionName)); @@ -1008,10 +980,9 @@ public Expression resolveFunction(@Nonnull final String functionName, @Nonnull C * * @return An {@link Expression} representing the resolved SQL window function. */ - @Nonnull - public Expression resolveWindowFunction(@Nonnull final String functionName, boolean flattenSingleItemRecords, - @Nonnull final WindowSpecExpression windowSpecExpression, - @Nonnull final Expressions arguments) { + public Expression resolveWindowFunction(final String functionName, boolean flattenSingleItemRecords, + final WindowSpecExpression windowSpecExpression, + final Expressions arguments) { final var windowSpecification = windowSpecExpression.toWindowSpecification(); var callSiteArguments = arguments.toCallSiteArguments(flattenSingleItemRecords) .withWindowSpecification(windowSpecification); @@ -1022,8 +993,7 @@ public Expression resolveWindowFunction(@Nonnull final String functionName, bool return resolveFunction(functionName, callSiteArguments, flattenSingleItemRecords); } - @Nonnull - private static CallSiteArguments.Options toCallSiteOptions(@Nonnull final Expressions windowOptions) { + private static CallSiteArguments.Options toCallSiteOptions(final Expressions windowOptions) { final var optionsBuilder = CallSiteArguments.Options.builder(); for (final var option : windowOptions) { Assert.thatUnchecked(option.getName().isPresent(), ErrorCode.SYNTAX_ERROR, @@ -1043,7 +1013,7 @@ private static CallSiteArguments.Options toCallSiteOptions(@Nonnull final Expres return optionsBuilder.build(); } - private void processFunctionSideEffects(@Nonnull final CatalogedFunction builtInFunction) { + private void processFunctionSideEffects(final CatalogedFunction builtInFunction) { if (!(builtInFunction instanceof WithPlanGenerationSideEffects)) { return; } @@ -1069,8 +1039,7 @@ private void processFunctionSideEffects(@Nonnull final CatalogedFunction builtIn * * @return A {@link LogicalOperator} representing the semantics of the requested SQL table function. */ - @Nonnull - public LogicalOperator resolveTableFunction(@Nonnull final Identifier functionName, @Nonnull final Expressions arguments, + public LogicalOperator resolveTableFunction(final Identifier functionName, final Expressions arguments, boolean flattenSingleItemRecords) { Assert.thatUnchecked(functionCatalog.containsFunction(functionName.getName()), ErrorCode.UNDEFINED_FUNCTION, () -> String.format(Locale.ROOT, "Unknown function %s", functionName)); @@ -1098,8 +1067,7 @@ public LogicalOperator resolveTableFunction(@Nonnull final Identifier functionNa return LogicalOperator.newNamedOperator(functionName, Expressions.fromQuantifier(topQun), topQun); } - @Nonnull - public LogicalOperator resolveView(@Nonnull final Identifier viewIdentifier) { + public LogicalOperator resolveView(final Identifier viewIdentifier) { final View view; try { view = Assert.optionalUnchecked(metadataCatalog.findViewByName(viewIdentifier.getName())); @@ -1111,13 +1079,13 @@ public LogicalOperator resolveView(@Nonnull final Identifier viewIdentifier) { } // TODO: this will be removed once we unify both Java- and SQL-UDFs. - public boolean isJavaCallFunction(@Nonnull final String functionName) { + public boolean isJavaCallFunction(final String functionName) { return functionCatalog.isJavaCallFunction(functionName); } - public boolean containsReferencesTo(@Nonnull final ParseTree parseTree, - @Nonnull final Identifier identifier, - @Nonnull final Function idParser) { + public boolean containsReferencesTo(final ParseTree parseTree, + final Identifier identifier, + final Function idParser) { return ParseHelpers.ParseTreeLikeAdapter.from(parseTree).preOrderStream() .map(ParseHelpers.ParseTreeLikeAdapter::getParseTree) .anyMatch(child -> (child instanceof RelationalParser.TableNameContext) @@ -1134,12 +1102,11 @@ public boolean containsReferencesTo(@Nonnull final ParseTree parseTree, * @param queryVisitor A query visitor instance. * @return the type of recursive query, as identified by the type of the first non-recursive branch. */ - @Nonnull - public Optional getRecursiveCteType(@Nonnull final RelationalParser.QueryContext namedQueryBody, - @Nonnull final Identifier queryName, - @Nonnull final Function idParser, - @Nonnull final Function> memoizer, - @Nonnull final QueryVisitor queryVisitor) { + public Optional getRecursiveCteType(final RelationalParser.QueryContext namedQueryBody, + final Identifier queryName, + final Function idParser, + final Function> memoizer, + final QueryVisitor queryVisitor) { final AtomicReference> result = new AtomicReference<>(Optional.empty()); recursiveQueryTraversal(namedQueryBody, queryName, idParser, nonRecursiveBranch -> { @@ -1164,12 +1131,11 @@ public Optional getRecursiveCteType(@Nonnull final RelationalParser.QueryC * @param queryVisitor A query visitor instance. * @return A partitioning of recursive query into a list of non-recursive logical operators and list of recursive logical operators. */ - @Nonnull - public NonnullPair, List> partitionRecursiveQuery(@Nonnull final RelationalParser.QueryContext namedQueryBody, - @Nonnull final Identifier queryName, - @Nonnull final Function idParser, - @Nonnull final Function> memoizer, - @Nonnull final QueryVisitor queryVisitor) { + public NonnullPair, List> partitionRecursiveQuery(final RelationalParser.QueryContext namedQueryBody, + final Identifier queryName, + final Function idParser, + final Function> memoizer, + final QueryVisitor queryVisitor) { final var nonRecursiveBranchesBuilder = ImmutableList.builder(); final var recursiveBranchesBuilder = ImmutableList.builder(); @@ -1185,11 +1151,11 @@ public NonnullPair, List> partitionRecurs return NonnullPair.of(nonRecursiveBranchesBuilder.build(), recursiveBranchesBuilder.build()); } - private void recursiveQueryTraversal(@Nonnull final RelationalParser.QueryContext namedQueryBody, - @Nonnull final Identifier queryName, - @Nonnull final Function idParser, - @Nonnull final Consumer nonRecursiveBranchConsumer, - @Nonnull final Consumer recursiveBranchConsumer) { + private void recursiveQueryTraversal(final RelationalParser.QueryContext namedQueryBody, + final Identifier queryName, + final Function idParser, + final Consumer nonRecursiveBranchConsumer, + final Consumer recursiveBranchConsumer) { final var hasNestedCtes = namedQueryBody.ctes() != null; if (hasNestedCtes) { for (final var nestedNamedQuery : namedQueryBody.ctes().namedQuery()) { @@ -1266,11 +1232,10 @@ public ParseTree getChild(int i) { } } - @Nonnull - private static LogicalOperator handleQueryFragment(@Nonnull final ParserRuleContext queryFragment, - @Nonnull final RelationalParser.QueryContext namedQueryBody, - @Nonnull final Function> memoizer, - @Nonnull final QueryVisitor queryVisitor) { + private static LogicalOperator handleQueryFragment(final ParserRuleContext queryFragment, + final RelationalParser.QueryContext namedQueryBody, + final Function> memoizer, + final QueryVisitor queryVisitor) { LogicalOperator logicalOperator; if (namedQueryBody.ctes() != null) { final var ctes = namedQueryBody.ctes(); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Star.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Star.java index ea8d68bb512..4aa24383d37 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Star.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Star.java @@ -32,8 +32,6 @@ import com.apple.foundationdb.relational.util.Assert; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; - -import javax.annotation.Nonnull; import java.util.Collection; import java.util.List; import java.util.Objects; @@ -48,11 +46,10 @@ @API(API.Status.EXPERIMENTAL) public final class Star extends Expression { - @Nonnull private final List expansion; - private Star(@Nonnull Optional qualifier, @Nonnull DataType dataType, @Nonnull Value expression, - @Nonnull Iterable expansion) { + private Star(Optional qualifier, DataType dataType, Value expression, + Iterable expansion) { super(qualifier, dataType, expression); Assert.thatUnchecked(expression.getResultType().isRecord()); Assert.thatUnchecked(dataType.getCode() == DataType.Code.STRUCT); @@ -60,20 +57,17 @@ private Star(@Nonnull Optional qualifier, @Nonnull DataType dataType this.expansion = ImmutableList.copyOf(expansion); } - @Nonnull @Override - protected Expression createNew(@Nonnull Optional newName, @Nonnull DataType newDataType, @Nonnull Value newUnderlying, @Nonnull Visibility newVisibility) { + protected Expression createNew(Optional newName, DataType newDataType, Value newUnderlying, Visibility newVisibility) { throw new RelationalException("attempt to recreate new star expression", ErrorCode.INTERNAL_ERROR).toUncheckedWrappedException(); } - @Nonnull public List getExpansion() { return expansion; } - @Nonnull @Override - public Expression withQualifier(@Nonnull Collection qualifier) { + public Expression withQualifier(Collection qualifier) { if (getName().isEmpty()) { return this; } @@ -86,16 +80,14 @@ public Expression withQualifier(@Nonnull Collection qualifier) { return this; } - @Nonnull @Override - public Expression withName(@Nonnull Identifier name) { + public Expression withName(Identifier name) { Assert.failUnchecked("attempt to name a star expression"); return null; } - @Nonnull @Override - public Expression withUnderlying(@Nonnull Value underlying) { + public Expression withUnderlying(Value underlying) { Assert.failUnchecked("attempt to replace underlying value of a star expression"); return null; } @@ -108,13 +100,11 @@ public Expression withUnderlying(@Nonnull Value underlying) { * @return a new {@link Expressions} list where each {@link Expression} internal {@link Value} with {@link LiteralValue}s * instead of any {@link ConstantObjectValue}s. */ - @Nonnull @Override - public Expressions dereferenced(@Nonnull Literals literals) { + public Expressions dereferenced(Literals literals) { return Expressions.of(expansion).dereferenced(literals); } - @Nonnull @Override public EphemeralExpression asEphemeral() { throw new RelationalException("attempt to create an ephemeral expression from a star", ErrorCode.INTERNAL_ERROR).toUncheckedWrappedException(); @@ -128,27 +118,24 @@ public String toString() { .collect(Collectors.joining(",")) + "|" + getDataType() + "| ⇾ " + getUnderlying(); } - @Nonnull - public static Star overQuantifier(@Nonnull Optional qualifier, - @Nonnull Value quantifier, - @Nonnull String typeName, - @Nonnull Expressions expansion) { + public static Star overQuantifier(Optional qualifier, + Value quantifier, + String typeName, + Expressions expansion) { final var starType = createStarType(typeName, expansion); return new Star(qualifier, starType, ensureValueConsistentWithExpansion(quantifier, expansion), expansion); } - @Nonnull - public static Star overQuantifiers(@Nonnull Optional qualifier, - @Nonnull List quantifiers, - @Nonnull String typeName, - @Nonnull Expressions expansion) { + public static Star overQuantifiers(Optional qualifier, + List quantifiers, + String typeName, + Expressions expansion) { final var underlyingStarType = quantifiers.size() == 1 ? quantifiers.get(0) : RecordConstructorValue.ofUnnamed(quantifiers); final var starType = createStarType(typeName, expansion); return new Star(qualifier, starType, ensureValueConsistentWithExpansion(underlyingStarType, expansion), expansion); } - @Nonnull - private static Value ensureValueConsistentWithExpansion(@Nonnull Value possibleValue, @Nonnull Expressions expansion) { + private static Value ensureValueConsistentWithExpansion(Value possibleValue, Expressions expansion) { // Try expanding the expansion and creating a record constructor value. If it has the same type as a proposed // pre-existing value, use that instead. This allows us to avoid inserting unnecessary RCVs if there's already // a value of the correct type, but it also allows us to modify the underlying type coming from a quantifier @@ -161,17 +148,15 @@ private static Value ensureValueConsistentWithExpansion(@Nonnull Value possibleV } } - @Nonnull - public static Star overIndividualExpressions(@Nonnull Optional qualifier, - @Nonnull String typeName, - @Nonnull Expressions expansion) { + public static Star overIndividualExpressions(Optional qualifier, + String typeName, + Expressions expansion) { final var starType = createStarType(typeName, expansion); return new Star(qualifier, starType, RecordConstructorValue.ofColumns(expansion.underlyingAsColumns()), expansion); } - @Nonnull - private static DataType.StructType createStarType(@Nonnull String name, - @Nonnull Expressions expansion) { + private static DataType.StructType createStarType(String name, + Expressions expansion) { final ImmutableList.Builder fields = ImmutableList.builder(); int i = 0; for (final var expression : expansion) { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/StringTrieNode.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/StringTrieNode.java index 56ccd1290a9..b95d5b97312 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/StringTrieNode.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/StringTrieNode.java @@ -24,15 +24,12 @@ import com.apple.foundationdb.record.util.TrieNode; import com.apple.foundationdb.relational.util.SpotBugsSuppressWarnings; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.Map; @SpotBugsSuppressWarnings(value = "SING_SINGLETON_HAS_NONPRIVATE_CONSTRUCTOR", justification = "Singleton designation is a false positive") @API(API.Status.EXPERIMENTAL) public class StringTrieNode extends TrieNode.AbstractTrieNode { - @Nonnull private static final StringTrieNode LEAF = new StringTrieNode(null); public StringTrieNode(@Nullable Map childrenMap) { @@ -43,13 +40,11 @@ public StringTrieNode(@Nullable Void value, @Nullable Map> explainSuppliers) { + public ExplainTokensWithPrecedence explain(final Iterable> explainSuppliers) { Verify.verify(Iterables.isEmpty(explainSuppliers)); return ExplainTokensWithPrecedence.of(new ExplainTokens().addKeyword("TRUE")); } @Override public Optional toQueryPredicate(@Nullable TypeRepository typeRepository, - @Nonnull Set localAliases) { + Set localAliases) { return Optional.of(ConstantPredicate.TRUE); } - @Nonnull @Override protected Iterable computeChildren() { return ImmutableList.of(); @@ -86,7 +81,7 @@ protected Iterable computeChildren() { @Nullable @Override - public Object eval(@Nullable final FDBRecordStoreBase store, @Nonnull EvaluationContext context) { + public Object eval(@Nullable final FDBRecordStoreBase store, EvaluationContext context) { return true; } @@ -96,49 +91,43 @@ public int hashCodeWithoutChildren() { } @Override - public int planHash(@Nonnull PlanHashMode mode) { + public int planHash(PlanHashMode mode) { return hashCodeWithoutChildren(); } - @Nonnull public static TautologicalValue getInstance() { return INSTANCE; } - @Nonnull @Override - public PValue toValueProto(@Nonnull final PlanSerializationContext serializationContext) { + public PValue toValueProto(final PlanSerializationContext serializationContext) { return PValue.newBuilder() .setAdditionalValues(PlanSerialization.protoObjectToAny(serializationContext, toProto(serializationContext))) .build(); } - @Nonnull @Override - public PTautologicalValue toProto(@Nonnull final PlanSerializationContext planSerializationContext) { + public PTautologicalValue toProto(final PlanSerializationContext planSerializationContext) { return PTautologicalValue.newBuilder().build(); } - @Nonnull - public static TautologicalValue fromProto(@Nonnull final PlanSerializationContext serializationContext, - @Nonnull final PTautologicalValue tautologicalValueProto) { + public static TautologicalValue fromProto(final PlanSerializationContext serializationContext, + final PTautologicalValue tautologicalValueProto) { return getInstance(); } @AutoService(PlanDeserializer.class) @SuppressWarnings("unused") public static class Deserializer implements PlanDeserializer { - @Nonnull @Override public Class getProtoMessageClass() { return PTautologicalValue.class; } - @Nonnull @Override - public TautologicalValue fromProto(@Nonnull final PlanSerializationContext serializationContext, - @Nonnull final PTautologicalValue tautologicalValueProto) { + public TautologicalValue fromProto(final PlanSerializationContext serializationContext, + final PTautologicalValue tautologicalValueProto) { return TautologicalValue.fromProto(serializationContext, tautologicalValueProto); } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/WindowSpecExpression.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/WindowSpecExpression.java index 5c0b1861003..8371e121c92 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/WindowSpecExpression.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/WindowSpecExpression.java @@ -24,9 +24,6 @@ import com.apple.foundationdb.record.query.plan.cascades.WindowOrderingPart; import com.google.common.collect.ImmutableList; import com.google.common.collect.Streams; - -import javax.annotation.Nonnull; - /** * Helper class that captures the components of an SQL {@code OVER} clause used in window functions. *

@@ -43,18 +40,15 @@ */ public final class WindowSpecExpression { - @Nonnull private final Expressions partitions; - @Nonnull private final Iterable orderByExpressions; - @Nonnull private final Expressions windowOptions; - private WindowSpecExpression(@Nonnull final Expressions partitions, - @Nonnull final Iterable orderByExpressions, - @Nonnull final Expressions windowOptions) { + private WindowSpecExpression(final Expressions partitions, + final Iterable orderByExpressions, + final Expressions windowOptions) { this.partitions = partitions; this.orderByExpressions = orderByExpressions; this.windowOptions = windowOptions; @@ -67,10 +61,9 @@ private WindowSpecExpression(@Nonnull final Expressions partitions, * @param orderByExpressions the ordering expressions (corresponds to ORDER BY clause) * @return a new OverExpression instance */ - @Nonnull - public static WindowSpecExpression of(@Nonnull final Expressions partitions, - @Nonnull final Iterable orderByExpressions, - @Nonnull final Expressions windowOptions) { + public static WindowSpecExpression of(final Expressions partitions, + final Iterable orderByExpressions, + final Expressions windowOptions) { return new WindowSpecExpression(partitions, orderByExpressions, windowOptions); } @@ -79,7 +72,6 @@ public static WindowSpecExpression of(@Nonnull final Expressions partitions, * * @return the partition expressions (PARTITION BY clause) */ - @Nonnull public Expressions getPartitions() { return partitions; } @@ -89,12 +81,10 @@ public Expressions getPartitions() { * * @return the ordering expressions (ORDER BY clause) */ - @Nonnull public Iterable getOrderByExpressions() { return orderByExpressions; } - @Nonnull public Expressions getWindowOptions() { return windowOptions; } @@ -105,7 +95,6 @@ public Expressions getWindowOptions() { * * @return the window specification to attach to a windowed call site */ - @Nonnull public CallSiteArguments.WindowSpecification toWindowSpecification() { final var partitioningValues = Streams.stream(partitions.underlying()) .collect(ImmutableList.toImmutableList()); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/AbstractCache.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/AbstractCache.java index 9186ed05146..b93b21e4c2b 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/AbstractCache.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/AbstractCache.java @@ -23,9 +23,7 @@ import com.apple.foundationdb.record.util.pair.NonnullPair; import com.apple.foundationdb.relational.api.metrics.MetricCollector; import com.google.common.annotations.VisibleForTesting; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import javax.annotation.concurrent.ThreadSafe; import java.util.Map; import java.util.Set; @@ -55,68 +53,54 @@ public abstract class CacheStatistics { public abstract long numEntriesSlow(); @Nullable - public abstract Long numSecondaryEntries(@Nonnull K key); + public abstract Long numSecondaryEntries(K key); @Nullable - public abstract Long numTertiaryEntries(@Nonnull K key, @Nonnull S secondaryKey); + public abstract Long numTertiaryEntries(K key, S secondaryKey); @VisibleForTesting @Nullable - public abstract Long numSecondaryEntriesSlow(@Nonnull K key); + public abstract Long numSecondaryEntriesSlow(K key); @VisibleForTesting @Nullable - public abstract Long numTertiaryEntriesSlow(@Nonnull K key, @Nonnull S secondaryKey); + public abstract Long numTertiaryEntriesSlow(K key, S secondaryKey); - @Nonnull public abstract Set getAllKeys(); - @Nonnull - public abstract Set getAllSecondaryKeys(@Nonnull K key); + public abstract Set getAllSecondaryKeys(K key); - @Nonnull - public abstract Set getAllTertiaryKeys(@Nonnull K key, @Nonnull S secondaryKey); + public abstract Set getAllTertiaryKeys(K key, S secondaryKey); - @Nonnull public abstract Map> getAllMappings(); - @Nonnull - public abstract Map> getAllSecondaryMappings(@Nonnull K key); + public abstract Map> getAllSecondaryMappings(K key); - @Nonnull - public abstract Map getAllTertiaryMappings(@Nonnull K key, @Nonnull S secondaryKey); + public abstract Map getAllTertiaryMappings(K key, S secondaryKey); public abstract long numHits(); - @Nonnull - public abstract Long numSecondaryHits(@Nonnull K key); + public abstract Long numSecondaryHits(K key); - @Nonnull - public abstract Long numTertiaryHits(@Nonnull K key, @Nonnull S secondaryKey); + public abstract Long numTertiaryHits(K key, S secondaryKey); public abstract long numMisses(); - @Nonnull - public abstract Long numSecondaryMisses(@Nonnull K key); + public abstract Long numSecondaryMisses(K key); - @Nonnull - public abstract Long numTertiaryMisses(@Nonnull K key, @Nonnull S secondaryKey); + public abstract Long numTertiaryMisses(K key, S secondaryKey); public abstract long numWrites(); - @Nonnull - public abstract Long numSecondaryWrites(@Nonnull K key); + public abstract Long numSecondaryWrites(K key); - @Nonnull - public abstract Long numTertiaryWrites(@Nonnull K key, @Nonnull S secondaryKey); + public abstract Long numTertiaryWrites(K key, S secondaryKey); public abstract long numReads(); - @Nonnull - public abstract Long numSecondaryReads(@Nonnull K key); + public abstract Long numSecondaryReads(K key); - @Nonnull - public abstract Long numTertiaryReads(@Nonnull K key, @Nonnull S secondaryKey); + public abstract Long numTertiaryReads(K key, S secondaryKey); } /** @@ -132,14 +116,13 @@ public abstract class CacheStatistics { * @param metricCollector metric collector to consume events from interacting with the cache. * @return The value referenced {@code key} and {@code secondaryKey}. */ - @Nonnull - public abstract V reduce(@Nonnull K key, - @Nonnull S secondaryKey, - @Nonnull T tertiaryKey, - @Nonnull Supplier> tertiaryKeyValueSupplier, - @Nonnull Function valueWithEnvironmentDecorator, - @Nonnull Function, V> reductionFunction, - @Nonnull MetricCollector metricCollector); + public abstract V reduce(K key, + S secondaryKey, + T tertiaryKey, + Supplier> tertiaryKeyValueSupplier, + Function valueWithEnvironmentDecorator, + Function, V> reductionFunction, + MetricCollector metricCollector); /** * Retrieves the statistics of the cache. diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/MultiStageCache.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/MultiStageCache.java index c5e60b66711..21ed72e4966 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/MultiStageCache.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/MultiStageCache.java @@ -32,9 +32,7 @@ import com.github.benmanes.caffeine.cache.RemovalListener; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Ticker; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.time.Duration; import java.util.AbstractMap; import java.util.Map; @@ -95,7 +93,6 @@ @API(API.Status.EXPERIMENTAL) public class MultiStageCache extends AbstractCache { - @Nonnull private final Cache>> mainCache; private final AtomicInteger pendingPrimaryLruEvictions = new AtomicInteger(0); @@ -165,15 +162,14 @@ protected MultiStageCache(int size, } @SuppressWarnings("UnstableApiUsage") - @Nonnull @Override - public V reduce(@Nonnull final K key, - @Nonnull final S secondaryKey, - @Nonnull final T tertiaryKey, - @Nonnull final Supplier> tertiaryKeyValueSupplier, - @Nonnull final Function valueWithEnvironmentDecorator, - @Nonnull final Function, V> reductionFunction, - @Nonnull final MetricCollector metricCollector) { + public V reduce(final K key, + final S secondaryKey, + final T tertiaryKey, + final Supplier> tertiaryKeyValueSupplier, + final Function valueWithEnvironmentDecorator, + final Function, V> reductionFunction, + final MetricCollector metricCollector) { metricCollector.increment(RelationalMetric.RelationalCount.PLAN_CACHE_PRIMARY_LRU_EVICTION, pendingPrimaryLruEvictions.getAndSet(0)); metricCollector.increment(RelationalMetric.RelationalCount.PLAN_CACHE_SECONDARY_LRU_EVICTION, pendingSecondaryLruEvictions.getAndSet(0)); metricCollector.increment(RelationalMetric.RelationalCount.PLAN_CACHE_TERTIARY_LRU_EVICTION, pendingTertiaryLruEvictions.getAndSet(0)); @@ -264,7 +260,7 @@ public long numEntriesSlow() { @Nullable @Override - public Long numSecondaryEntries(@Nonnull final K key) { + public Long numSecondaryEntries(final K key) { final var secondary = mainCache.getIfPresent(key); if (secondary != null) { return secondary.estimatedSize(); @@ -274,7 +270,7 @@ public Long numSecondaryEntries(@Nonnull final K key) { @Nullable @Override - public Long numTertiaryEntries(@Nonnull K key, @Nonnull S secondaryKey) { + public Long numTertiaryEntries(K key, S secondaryKey) { final var secondary = mainCache.getIfPresent(key); if (secondary != null) { final var tertiary = secondary.getIfPresent(secondaryKey); @@ -287,7 +283,7 @@ public Long numTertiaryEntries(@Nonnull K key, @Nonnull S secondaryKey) { @Nullable @Override - public Long numSecondaryEntriesSlow(@Nonnull final K key) { + public Long numSecondaryEntriesSlow(final K key) { final var secondary = mainCache.getIfPresent(key); if (secondary != null) { return (long) secondary.asMap().size(); @@ -297,7 +293,7 @@ public Long numSecondaryEntriesSlow(@Nonnull final K key) { @Nullable @Override - public Long numTertiaryEntriesSlow(@Nonnull K key, @Nonnull S secondaryKey) { + public Long numTertiaryEntriesSlow(K key, S secondaryKey) { final var secondary = mainCache.getIfPresent(key); if (secondary != null) { final var tertiary = secondary.getIfPresent(secondaryKey); @@ -308,15 +304,13 @@ public Long numTertiaryEntriesSlow(@Nonnull K key, @Nonnull S secondaryKey) { return null; } - @Nonnull @Override public Set getAllKeys() { return mainCache.asMap().keySet(); } - @Nonnull @Override - public Set getAllSecondaryKeys(@Nonnull final K key) { + public Set getAllSecondaryKeys(final K key) { final var secondary = mainCache.getIfPresent(key); if (secondary != null) { return secondary.asMap().keySet(); @@ -324,9 +318,8 @@ public Set getAllSecondaryKeys(@Nonnull final K key) { return Set.of(); } - @Nonnull @Override - public Set getAllTertiaryKeys(@Nonnull K key, @Nonnull S secondaryKey) { + public Set getAllTertiaryKeys(K key, S secondaryKey) { final var secondary = mainCache.getIfPresent(key); if (secondary != null) { final var tertiary = secondary.getIfPresent(secondaryKey); @@ -337,15 +330,13 @@ public Set getAllTertiaryKeys(@Nonnull K key, @Nonnull S secondaryKey) { return Set.of(); } - @Nonnull @Override public Map> getAllMappings() { return mainCache.asMap().entrySet().stream().map(e -> new AbstractMap.SimpleEntry<>(e.getKey(), e.getValue().asMap().keySet())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } - @Nonnull @Override - public Map> getAllSecondaryMappings(@Nonnull final K key) { + public Map> getAllSecondaryMappings(final K key) { final var secondary = mainCache.getIfPresent(key); if (secondary != null) { return secondary.asMap().entrySet().stream().map(e -> new AbstractMap.SimpleEntry<>(e.getKey(), e.getValue().asMap().keySet())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); @@ -353,9 +344,8 @@ public Map> getAllSecondaryMappings(@Nonnull final K key) { return Map.of(); } - @Nonnull @Override - public Map getAllTertiaryMappings(@Nonnull K key, @Nonnull S secondaryKey) { + public Map getAllTertiaryMappings(K key, S secondaryKey) { final var secondary = mainCache.getIfPresent(key); if (secondary != null) { final var tertiary = secondary.getIfPresent(secondaryKey); @@ -371,9 +361,8 @@ public long numHits() { return mainCache.stats().hitCount(); } - @Nonnull @Override - public Long numSecondaryHits(@Nonnull final K key) { + public Long numSecondaryHits(final K key) { final var secondary = mainCache.getIfPresent(key); if (secondary != null) { return secondary.stats().hitCount(); @@ -381,9 +370,8 @@ public Long numSecondaryHits(@Nonnull final K key) { return 0L; } - @Nonnull @Override - public Long numTertiaryHits(@Nonnull K key, @Nonnull S secondaryKey) { + public Long numTertiaryHits(K key, S secondaryKey) { final var secondary = mainCache.getIfPresent(key); if (secondary != null) { final var tertiary = secondary.getIfPresent(secondaryKey); @@ -399,9 +387,8 @@ public long numMisses() { return mainCache.stats().missCount(); } - @Nonnull @Override - public Long numSecondaryMisses(@Nonnull final K key) { + public Long numSecondaryMisses(final K key) { final var secondary = mainCache.getIfPresent(key); if (secondary != null) { return secondary.stats().missCount(); @@ -409,9 +396,8 @@ public Long numSecondaryMisses(@Nonnull final K key) { return 0L; } - @Nonnull @Override - public Long numTertiaryMisses(@Nonnull K key, @Nonnull S secondaryKey) { + public Long numTertiaryMisses(K key, S secondaryKey) { final var secondary = mainCache.getIfPresent(key); if (secondary != null) { final var tertiary = secondary.getIfPresent(secondaryKey); @@ -427,9 +413,8 @@ public long numWrites() { return mainCache.stats().loadCount(); } - @Nonnull @Override - public Long numSecondaryWrites(@Nonnull final K key) { + public Long numSecondaryWrites(final K key) { final var secondary = mainCache.getIfPresent(key); if (secondary != null) { return secondary.stats().loadCount(); @@ -437,9 +422,8 @@ public Long numSecondaryWrites(@Nonnull final K key) { return 0L; } - @Nonnull @Override - public Long numTertiaryWrites(@Nonnull K key, @Nonnull S secondaryKey) { + public Long numTertiaryWrites(K key, S secondaryKey) { final var secondary = mainCache.getIfPresent(key); if (secondary != null) { final var tertiary = secondary.getIfPresent(secondaryKey); @@ -455,9 +439,8 @@ public long numReads() { return mainCache.stats().requestCount(); } - @Nonnull @Override - public Long numSecondaryReads(@Nonnull final K key) { + public Long numSecondaryReads(final K key) { final var secondary = mainCache.getIfPresent(key); if (secondary != null) { return secondary.stats().requestCount(); @@ -465,9 +448,8 @@ public Long numSecondaryReads(@Nonnull final K key) { return 0L; } - @Nonnull @Override - public Long numTertiaryReads(@Nonnull K key, @Nonnull S secondaryKey) { + public Long numTertiaryReads(K key, S secondaryKey) { final var secondary = mainCache.getIfPresent(key); if (secondary != null) { final var tertiary = secondary.getIfPresent(secondaryKey); @@ -494,13 +476,10 @@ public abstract static class Builder 0, ErrorCode.INTERNAL_ERROR, "Invalid cache size '%d'", size); this.size = size; return self(); } - @Nonnull public B setSecondarySize(int secondarySize) { Assert.thatUnchecked(secondarySize > 0, ErrorCode.INTERNAL_ERROR, "Invalid secondary cache size '%d'", secondarySize); this.secondarySize = secondarySize; return self(); } - @Nonnull public B setTertiarySize(int tertiarySize) { Assert.thatUnchecked(tertiarySize > 0, ErrorCode.INTERNAL_ERROR, "Invalid tertiary cache size '%d'", tertiarySize); this.tertiarySize = tertiarySize; return self(); } - @Nonnull public B setTtl(long ttlMillis) { return setTtl(ttlMillis, TimeUnit.MILLISECONDS); } - @Nonnull - public B setTtl(long ttl, @Nonnull final TimeUnit timeUnit) { + public B setTtl(long ttl, final TimeUnit timeUnit) { Assert.thatUnchecked(ttl > 0, ErrorCode.INTERNAL_ERROR, "Invalid cache ttl '%d'", ttl); this.ttl = ttl; this.ttlTimeUnit = timeUnit; return self(); } - @Nonnull public B setSecondaryTtl(long secondaryTtlMillis) { return setSecondaryTtl(secondaryTtlMillis, TimeUnit.MILLISECONDS); } - @Nonnull - public B setSecondaryTtl(long secondaryTtl, @Nonnull final TimeUnit timeUnit) { + public B setSecondaryTtl(long secondaryTtl, final TimeUnit timeUnit) { Assert.thatUnchecked(secondaryTtl > 0, ErrorCode.INTERNAL_ERROR, "Invalid cache secondaryTtl '%d'", secondaryTtl); this.secondaryTtl = secondaryTtl; this.secondaryTtlTimeUnit = timeUnit; return self(); } - @Nonnull public B setTertiaryTtl(long tertiaryTtlMillis) { return setTertiaryTtl(tertiaryTtlMillis, TimeUnit.MILLISECONDS); } - @Nonnull - public B setTertiaryTtl(long tertiaryTtl, @Nonnull final TimeUnit timeUnit) { + public B setTertiaryTtl(long tertiaryTtl, final TimeUnit timeUnit) { Assert.thatUnchecked(tertiaryTtl > 0, ErrorCode.INTERNAL_ERROR, "Invalid cache tertiaryTtl '%d'", tertiaryTtl); this.tertiaryTtl = tertiaryTtl; this.tertiaryTtlTimeUnit = timeUnit; return self(); } - @Nonnull - public B setTicker(@Nonnull final Ticker ticker) { + public B setTicker(final Ticker ticker) { this.ticker = ticker; return self(); } - @Nonnull - public B setExecutor(@Nonnull final Executor executor) { + public B setExecutor(final Executor executor) { this.executor = executor; return self(); } - @Nonnull - public B setSecondaryExecutor(@Nonnull final Executor secondaryExecutor) { + public B setSecondaryExecutor(final Executor secondaryExecutor) { this.secondaryExecutor = secondaryExecutor; return self(); } - @Nonnull - public B setTertiaryExecutor(@Nonnull final Executor tertiaryExecutor) { + public B setTertiaryExecutor(final Executor tertiaryExecutor) { this.tertiaryExecutor = tertiaryExecutor; return self(); } - @Nonnull public MultiStageCache build() { return new MultiStageCache<>(size, secondarySize, tertiarySize, ttl, ttlTimeUnit, secondaryTtl, secondaryTtlTimeUnit, tertiaryTtl, tertiaryTtlTimeUnit, executor, secondaryExecutor, tertiaryExecutor, ticker); } } public static class MultiStageCacheBuilder extends Builder> { - @Nonnull @Override protected MultiStageCacheBuilder self() { return this; } } - @Nonnull public static MultiStageCacheBuilder newMultiStageCacheBuilder() { return new MultiStageCacheBuilder<>(); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/PhysicalPlanEquivalence.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/PhysicalPlanEquivalence.java index 888f555f3be..c6b8f9525aa 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/PhysicalPlanEquivalence.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/PhysicalPlanEquivalence.java @@ -30,8 +30,6 @@ import com.apple.foundationdb.relational.util.Assert; import com.google.common.annotations.VisibleForTesting; - -import javax.annotation.Nonnull; import java.util.Objects; import java.util.Optional; @@ -57,15 +55,13 @@ @API(API.Status.EXPERIMENTAL) public final class PhysicalPlanEquivalence { - @Nonnull private final Optional constraint; - @Nonnull private final Optional evaluationContext; @VisibleForTesting - PhysicalPlanEquivalence(@Nonnull final Optional constraint, - @Nonnull final Optional evaluationContext) { + PhysicalPlanEquivalence(final Optional constraint, + final Optional evaluationContext) { Assert.thatUnchecked(constraint.isPresent() ^ evaluationContext.isPresent(), ErrorCode.INTERNAL_ERROR, "Either constraint or evaluation context must be set (but not both)" ); @@ -138,18 +134,15 @@ public int hashCode() { return 0; } - @Nonnull - public PhysicalPlanEquivalence withConstraint(@Nonnull final QueryPlanConstraint constraint) { + public PhysicalPlanEquivalence withConstraint(final QueryPlanConstraint constraint) { return new PhysicalPlanEquivalence(Optional.of(constraint), Optional.empty()); } - @Nonnull - public static PhysicalPlanEquivalence of(@Nonnull final EvaluationContext evaluationContext) { + public static PhysicalPlanEquivalence of(final EvaluationContext evaluationContext) { return new PhysicalPlanEquivalence(Optional.empty(), Optional.of(evaluationContext)); } - @Nonnull - public static PhysicalPlanEquivalence of(@Nonnull final QueryPlanConstraint constraint) { + public static PhysicalPlanEquivalence of(final QueryPlanConstraint constraint) { return new PhysicalPlanEquivalence(Optional.of(constraint), Optional.empty()); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/QueryCacheKey.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/QueryCacheKey.java index d42b8a174ad..59443b74fda 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/QueryCacheKey.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/QueryCacheKey.java @@ -24,8 +24,6 @@ import com.apple.foundationdb.relational.recordlayer.query.AstNormalizer; import com.apple.foundationdb.relational.recordlayer.query.PlannerConfiguration; - -import javax.annotation.Nonnull; import java.util.Objects; /** @@ -99,22 +97,19 @@ @API(API.Status.EXPERIMENTAL) public final class QueryCacheKey { - @Nonnull private final String canonicalQueryString; - @Nonnull private final PlannerConfiguration plannerConfiguration; - @Nonnull private final String auxiliaryMetadata; private final int schemaTemplateVersion; private final int memoizedHashCode; - private QueryCacheKey(@Nonnull final String canonicalQueryString, - @Nonnull final PlannerConfiguration plannerConfiguration, - @Nonnull final String auxiliaryMetadata, + private QueryCacheKey(final String canonicalQueryString, + final PlannerConfiguration plannerConfiguration, + final String auxiliaryMetadata, int schemaTemplateVersion) { this.canonicalQueryString = canonicalQueryString; this.schemaTemplateVersion = schemaTemplateVersion; @@ -147,7 +142,6 @@ public int hashCode() { return memoizedHashCode; } - @Nonnull public String getCanonicalQueryString() { return canonicalQueryString; } @@ -156,12 +150,10 @@ public int getSchemaTemplateVersion() { return schemaTemplateVersion; } - @Nonnull public PlannerConfiguration getPlannerConfiguration() { return plannerConfiguration; } - @Nonnull public String getAuxiliaryMetadata() { return auxiliaryMetadata; } @@ -171,10 +163,9 @@ public String toString() { return "(" + schemaTemplateVersion + " || " + auxiliaryMetadata + ")" + "||" + canonicalQueryString + "||" + memoizedHashCode; } - @Nonnull - public static QueryCacheKey of(@Nonnull final String query, - @Nonnull final PlannerConfiguration plannerConfiguration, - @Nonnull final String auxiliaryMetadata, + public static QueryCacheKey of(final String query, + final PlannerConfiguration plannerConfiguration, + final String auxiliaryMetadata, int schemaTemplateVersion) { return new QueryCacheKey(query, plannerConfiguration, auxiliaryMetadata, schemaTemplateVersion); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/RelationalPlanCache.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/RelationalPlanCache.java index 13e8192d8a8..a2ba7623cae 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/RelationalPlanCache.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/RelationalPlanCache.java @@ -24,9 +24,7 @@ import com.apple.foundationdb.relational.api.Options; import com.apple.foundationdb.relational.recordlayer.query.Plan; import com.google.common.base.Ticker; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; @@ -36,24 +34,21 @@ @API(API.Status.EXPERIMENTAL) public final class RelationalPlanCache extends MultiStageCache> { - @Nonnull private static final TimeUnit DEFAULT_TTL_TIME_UNIT = TimeUnit.MILLISECONDS; - @Nonnull private static final TimeUnit DEFAULT_SECONDARY_TTL_TIME_UNIT = TimeUnit.MILLISECONDS; - @Nonnull private static final TimeUnit DEFAULT_TERTIARY_TTL_TIME_UNIT = TimeUnit.MILLISECONDS; private RelationalPlanCache(int size, int secondarySize, int tertiarySize, long ttl, - @Nonnull final TimeUnit ttlTimeUnit, + final TimeUnit ttlTimeUnit, long secondaryTtl, - @Nonnull final TimeUnit secondaryTtlTimeUnit, + final TimeUnit secondaryTtlTimeUnit, long tertiaryTtl, - @Nonnull final TimeUnit tertiaryTtlTimeUnit, + final TimeUnit tertiaryTtlTimeUnit, @Nullable final Executor executor, @Nullable final Executor secondaryExecutor, @Nullable final Executor tertiaryExecutor, @@ -79,25 +74,21 @@ public RelationalCacheBuilder() { ticker = null; } - @Nonnull @Override public RelationalPlanCache build() { return new RelationalPlanCache(size, secondarySize, tertiarySize, ttl, ttlTimeUnit, secondaryTtl, secondaryTtlTimeUnit, tertiaryTtl, tertiaryTtlTimeUnit, executor, secondaryExecutor, tertiaryExecutor, ticker); } - @Nonnull @Override protected RelationalCacheBuilder self() { return this; } } - @Nonnull public static RelationalCacheBuilder newRelationalCacheBuilder() { return new RelationalCacheBuilder(); } - @Nonnull public static RelationalPlanCache buildWithDefaults() { return newRelationalCacheBuilder().build(); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/package-info.java index afd7bfa0ba8..5623711387f 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/package-info.java @@ -21,4 +21,7 @@ /** * This package contains logic related to plan caching. */ +@NullMarked package com.apple.foundationdb.relational.recordlayer.query.cache; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/MaterializedViewIndexGenerator.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/MaterializedViewIndexGenerator.java index 463367ecb4e..3a4a2a09283 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/MaterializedViewIndexGenerator.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/MaterializedViewIndexGenerator.java @@ -82,9 +82,7 @@ import com.google.common.collect.Iterators; import com.google.common.collect.Lists; import com.google.common.collect.PeekingIterator; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.ArrayList; import java.util.Collections; import java.util.IdentityHashMap; @@ -121,18 +119,15 @@ public final class MaterializedViewIndexGenerator { /** * Map from each correlation in the query plan to its list of results. */ - @Nonnull private final IdentityHashMap correlatedKeyExpressions = new IdentityHashMap<>(); - @Nonnull private final List relationalExpressions; - @Nonnull private final RelationalExpression relationalExpression; private final boolean useLegacyBasedExtremumEver; - private MaterializedViewIndexGenerator(@Nonnull RelationalExpression relationalExpression, boolean useLegacyBasedExtremumEver) { + private MaterializedViewIndexGenerator(RelationalExpression relationalExpression, boolean useLegacyBasedExtremumEver) { collectQuantifiers(relationalExpression); final var partialOrder = referencesAndDependencies().evaluate(Reference.initialOf(relationalExpression)); relationalExpressions = @@ -145,8 +140,7 @@ private MaterializedViewIndexGenerator(@Nonnull RelationalExpression relationalE this.useLegacyBasedExtremumEver = useLegacyBasedExtremumEver; } - @Nonnull - public RecordLayerIndex.Builder generate(@Nonnull RecordLayerSchemaTemplate.Builder schemaTemplateBuilder, @Nonnull String indexName, + public RecordLayerIndex.Builder generate(RecordLayerSchemaTemplate.Builder schemaTemplateBuilder, String indexName, boolean isUnique, boolean containsNullableArray, boolean generateKeyValueExpressionWithEmptyKey) { final String recordTypeName = getRecordTypeName(); // Have to use the storage name here because the index generator uses it @@ -245,8 +239,7 @@ public RecordLayerIndex.Builder generate(@Nonnull RecordLayerSchemaTemplate.Buil return indexBuilder; } - @Nonnull - private List collectResultValues(@Nonnull Value value) { + private List collectResultValues(Value value) { final var resultValues = simplify(value); final var isSingleAggregation = resultValues.size() == 1 && resultValues.get(0) instanceof IndexableAggregateValue; final var maybeGroupBy = relationalExpressions.stream().filter(exp -> exp instanceof GroupByExpression).findFirst(); @@ -298,9 +291,8 @@ private List collectResultValues(@Nonnull Value value) { } } - @Nonnull - private static List adjustGroupByFieldPaths(@Nonnull List resultValues, - @Nonnull GroupByExpression groupByExpression) { + private static List adjustGroupByFieldPaths(List resultValues, + GroupByExpression groupByExpression) { /* * This strips the root of the field path from every FieldValue that is referencing an attribute from the * underlying SELECT-WHERE expression. @@ -326,8 +318,7 @@ private static List adjustGroupByFieldPaths(@Nonnull List resultVa })).collect(ImmutableList.toImmutableList()); } - @Nonnull - private List simplify(@Nonnull Value value) { + private List simplify(Value value) { return Values.deconstructRecord(value) .stream() .map(this::dereference) @@ -335,9 +326,8 @@ private List simplify(@Nonnull Value value) { .collect(toList()); } - @Nonnull - private List getOrderByValues(@Nonnull RelationalExpression relationalExpression, - @Nonnull Map orderingFunctions) { + private List getOrderByValues(RelationalExpression relationalExpression, + Map orderingFunctions) { if (relationalExpression instanceof LogicalSortExpression) { final var logicalSortExpression = (LogicalSortExpression) relationalExpression; final var reverseAliasMap = AliasMap.ofAliases(Quantifier.current(), logicalSortExpression.getQuantifiers().get(0).getAlias()); @@ -384,7 +374,7 @@ private List getOrderByValues(@Nonnull RelationalExpression relationalExp return List.of(); } - private static List reorderValues(@Nonnull List values, @Nonnull List orderByValues) { + private static List reorderValues(List values, List orderByValues) { Assert.thatUnchecked(values.size() >= orderByValues.size()); if (orderByValues.isEmpty()) { return values; @@ -394,9 +384,8 @@ private static List reorderValues(@Nonnull List values, @Nonnull L } @SuppressWarnings({"OptionalIsPresent", "deprecation"}) - @Nonnull - private NonnullPair generateAggregateIndexKeyExpression(@Nonnull AggregateValue aggregateValue, - @Nonnull Optional maybeGroupingExpression) { + private NonnullPair generateAggregateIndexKeyExpression(AggregateValue aggregateValue, + Optional maybeGroupingExpression) { Assert.thatUnchecked(aggregateValue instanceof IndexableAggregateValue); final var indexableAggregateValue = (IndexableAggregateValue) aggregateValue; final var child = Iterables.getOnlyElement(aggregateValue.getChildren()); @@ -471,7 +460,7 @@ remove bitmap_bucket_offset(col) from groupingExpression if it exists return null if groupingExpression only contains bitmap_bucket_offset(col) */ @Nullable - private KeyExpression removeBitmapBucketOffset(@Nonnull KeyExpression groupingExpression) { + private KeyExpression removeBitmapBucketOffset(KeyExpression groupingExpression) { // groupingExpression looks like [*, bitmap_bucket_offset(C)+], so it is either a ThenKeyExpression or a FunctionKeyExpression Assert.thatUnchecked(groupingExpression instanceof ThenKeyExpression || groupingExpression instanceof FunctionKeyExpression, "Unsupported index definition, expecting column or function arguments in group by"); if (groupingExpression instanceof ThenKeyExpression) { @@ -493,8 +482,7 @@ private KeyExpression removeBitmapBucketOffset(@Nonnull KeyExpression groupingEx } } - @Nonnull - private KeyExpression generate(@Nonnull List fields, @Nonnull Map orderingFunctions) { + private KeyExpression generate(List fields, Map orderingFunctions) { if (fields.isEmpty()) { return EmptyKeyExpression.EMPTY; } else if (fields.size() == 1) { @@ -523,7 +511,6 @@ private KeyExpression generate(@Nonnull List fields, @Nonnull Map orderingFunctions) { var expr = toKeyExpression(value); if (orderingFunctions.containsKey(value)) { @@ -536,7 +523,6 @@ private KeyExpression toKeyExpression(Value value, Map orderingFu /** * Build the key expression representing the arguments of a {@link FunctionKeyExpression}. */ - @Nonnull private static KeyExpression buildArgumentKeyExpression(List argumentList) { if (argumentList.isEmpty()) { return empty(); @@ -547,8 +533,7 @@ private static KeyExpression buildArgumentKeyExpression(List argu } } - @Nonnull - private KeyExpression toKeyExpression(@Nonnull Value value) { + private KeyExpression toKeyExpression(Value value) { if (value instanceof FieldValue) { final FieldValue fieldValue = (FieldValue) value; return toKeyExpression(fieldValue.getFieldPath().getFieldAccessors().iterator(), KeyExpression.FanType.FanOut); @@ -581,9 +566,8 @@ private KeyExpression toKeyExpression(@Nonnull Value value) { } } - @Nonnull - private static KeyExpression toKeyExpression(@Nonnull FieldValueTrieNode trieNode, - @Nonnull Map orderingFunctions) { + private static KeyExpression toKeyExpression(FieldValueTrieNode trieNode, + Map orderingFunctions) { Assert.notNullUnchecked(trieNode.getChildrenMap()); Assert.thatUnchecked(!trieNode.getChildrenMap().isEmpty()); @@ -608,7 +592,7 @@ private static KeyExpression toKeyExpression(@Nonnull FieldValueTrieNode trieNod } } - private void checkValidity(@Nonnull List expressions) { + private void checkValidity(List expressions) { // there must be exactly one type full-unordered-scan, no joins, no self-joins. final var numScans = expressions.stream().filter(r -> r instanceof FullUnorderedScanExpression).count(); @@ -637,7 +621,7 @@ private void checkValidity(@Nonnull List express } @Nullable - public static QueryPredicate getTopLevelPredicate(@Nonnull List expressions) { + public static QueryPredicate getTopLevelPredicate(List expressions) { if (expressions.isEmpty()) { return null; } @@ -684,15 +668,14 @@ private static final class AnnotatedAccessor extends FieldValue.ResolvedAccessor private final int marker; - private AnnotatedAccessor(@Nonnull Type.Record.Field field, + private AnnotatedAccessor(Type.Record.Field field, int ordinal, int marker) { super(field, ordinal); this.marker = marker; } - @Nonnull - public static AnnotatedAccessor of(@Nonnull FieldValue.ResolvedAccessor resolvedAccessor, int marker) { + public static AnnotatedAccessor of(FieldValue.ResolvedAccessor resolvedAccessor, int marker) { return new AnnotatedAccessor(resolvedAccessor.getField(), resolvedAccessor.getOrdinal(), marker); } @@ -717,12 +700,12 @@ public int hashCode() { } } - private void collectQuantifiers(@Nonnull RelationalExpression relationalExpression) { + private void collectQuantifiers(RelationalExpression relationalExpression) { AtomicInteger counter = new AtomicInteger(0); collectQuantifiersInternal(relationalExpression, counter); } - private void collectQuantifiersInternal(@Nonnull RelationalExpression relationalExpression, @Nonnull AtomicInteger explodeCounter) { + private void collectQuantifiersInternal(RelationalExpression relationalExpression, AtomicInteger explodeCounter) { for (final var qun : relationalExpression.getQuantifiers()) { if (qun.getRangesOver().get() instanceof ExplodeExpression) { explodeCounter.incrementAndGet(); @@ -742,8 +725,7 @@ private void collectQuantifiersInternal(@Nonnull RelationalExpression relational } } - @Nonnull - private Value dereference(@Nonnull Value value) { + private Value dereference(Value value) { if (value instanceof RecordConstructorValue) { return RecordConstructorValue.ofColumns( ((RecordConstructorValue) value).getColumns() @@ -774,8 +756,7 @@ private Value dereference(@Nonnull Value value) { } } - @Nonnull - private KeyExpression toKeyExpression(@Nonnull Iterator resolvedAccessors, KeyExpression.FanType fanTypeForArray) { + private KeyExpression toKeyExpression(Iterator resolvedAccessors, KeyExpression.FanType fanTypeForArray) { Assert.thatUnchecked(resolvedAccessors.hasNext(), "cannot resolve empty list"); final FieldValue.ResolvedAccessor accessor = resolvedAccessors.next(); final KeyExpression expression = toFieldKeyExpression(accessor, fanTypeForArray); @@ -788,7 +769,6 @@ private KeyExpression toKeyExpression(@Nonnull Iterator r instanceof LogicalTypeFilterExpression) @@ -806,8 +786,7 @@ private String getRecordTypeName() { * @param fanTypeForArray The fan-out type to use for the {@code field} key expression in case the field is an * ARRAY. This should be either {@code FanOut} or {@code Concatenate}. */ - @Nonnull - private static KeyExpression toFieldKeyExpression(@Nonnull FieldValue.ResolvedAccessor accessor, KeyExpression.FanType fanTypeForArray) { + private static KeyExpression toFieldKeyExpression(FieldValue.ResolvedAccessor accessor, KeyExpression.FanType fanTypeForArray) { final Type.Record.Field fieldType = accessor.getField(); Assert.notNullUnchecked(fieldType.getFieldStorageName()); Assert.thatUnchecked(fanTypeForArray == KeyExpression.FanType.FanOut || fanTypeForArray == KeyExpression.FanType.Concatenate); @@ -826,8 +805,7 @@ private static KeyExpression toFieldKeyExpression(@Nonnull FieldValue.ResolvedAc return field(fieldType.getFieldStorageName(), fanType); } - @Nonnull - public static MaterializedViewIndexGenerator from(@Nonnull RelationalExpression relationalExpression, boolean useLongBasedExtremumEver) { + public static MaterializedViewIndexGenerator from(RelationalExpression relationalExpression, boolean useLongBasedExtremumEver) { return new MaterializedViewIndexGenerator(relationalExpression, useLongBasedExtremumEver); } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/OnSourceIndexGenerator.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/OnSourceIndexGenerator.java index 19e700e1975..1543a0cd4ae 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/OnSourceIndexGenerator.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/OnSourceIndexGenerator.java @@ -46,8 +46,6 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; - -import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -107,16 +105,12 @@ */ public final class OnSourceIndexGenerator { - @Nonnull private final Identifier indexName; - @Nonnull private final List keyColumns; - @Nonnull private final List valueColumns; - @Nonnull private final LogicalPlanFragment source; private final boolean isUnique; @@ -127,17 +121,15 @@ public final class OnSourceIndexGenerator { private final boolean generateKeyValueExpressionWithEmptyKey; - @Nonnull private final Map indexOptions; - @Nonnull private final RecordLayerSchemaTemplate.Builder metadataBuilder; - public OnSourceIndexGenerator(@Nonnull final Identifier indexName, @Nonnull final LogicalPlanFragment source, - @Nonnull final List keyColumns, @Nonnull final List valueColumns, + public OnSourceIndexGenerator(final Identifier indexName, final LogicalPlanFragment source, + final List keyColumns, final List valueColumns, final boolean isUnique, final boolean useLegacyExtremum, final boolean useNullableArrays, - final boolean generateKeyValueExpressionWithEmptyKey, @Nonnull final Map indexOptions, - @Nonnull final RecordLayerSchemaTemplate.Builder metadataBuilder) { + final boolean generateKeyValueExpressionWithEmptyKey, final Map indexOptions, + final RecordLayerSchemaTemplate.Builder metadataBuilder) { this.indexName = indexName; this.source = source; this.keyColumns = ImmutableList.copyOf(keyColumns); @@ -168,7 +160,6 @@ public OnSourceIndexGenerator(@Nonnull final Identifier indexName, @Nonnull fina * * @return a fully configured {@link RecordLayerIndex} ready to be added to the schema */ - @Nonnull public RecordLayerIndex.Builder generate() { final var keyIdentifiers = keyColumns.stream().map(IndexedColumn::getIdentifier).collect(ImmutableList.toImmutableList()); final var keyIdentifiersAsSet = ImmutableSet.copyOf(keyIdentifiers); @@ -231,20 +222,18 @@ public RecordLayerIndex.Builder generate() { public static final class IndexedColumn { - @Nonnull private final Identifier identifier; private final boolean isDescending; private final boolean isNullsLast; - private IndexedColumn(@Nonnull final Identifier identifier, boolean isDescending, boolean isNullsLast) { + private IndexedColumn(final Identifier identifier, boolean isDescending, boolean isNullsLast) { this.identifier = identifier; this.isDescending = isDescending; this.isNullsLast = isNullsLast; } - @Nonnull public Identifier getIdentifier() { return identifier; } @@ -257,8 +246,7 @@ public boolean isNullsLast() { return isNullsLast; } - @Nonnull - public static IndexedColumn of(@Nonnull final Identifier identifier, boolean isDescending, boolean isNullsLast) { + public static IndexedColumn of(final Identifier identifier, boolean isDescending, boolean isNullsLast) { return new IndexedColumn(identifier, isDescending, isNullsLast); } @@ -277,9 +265,8 @@ public static IndexedColumn of(@Nonnull final Identifier identifier, boolean isD * @param identifierVisitor the visitor used to extract the column identifier * @return an {@link IndexedColumn} representing the parsed column specification */ - @Nonnull - public static OnSourceIndexGenerator.IndexedColumn parseColSpec(@Nonnull final RelationalParser.IndexColumnSpecContext columnSpec, - @Nonnull final IdentifierVisitor identifierVisitor) { + public static OnSourceIndexGenerator.IndexedColumn parseColSpec(final RelationalParser.IndexColumnSpecContext columnSpec, + final IdentifierVisitor identifierVisitor) { final var columnId = identifierVisitor.visitUid(columnSpec.columnName); final var orderContext = columnSpec.orderClause(); @@ -299,15 +286,13 @@ public static OnSourceIndexGenerator.IndexedColumn parseColSpec(@Nonnull final R return OnSourceIndexGenerator.IndexedColumn.of(columnId, isDesc, nullsLast); } - @Nonnull - public static OnSourceIndexGenerator.IndexedColumn parseUid(@Nonnull final RelationalParser.UidContext uid, - @Nonnull final IdentifierVisitor identifierVisitor) { + public static OnSourceIndexGenerator.IndexedColumn parseUid(final RelationalParser.UidContext uid, + final IdentifierVisitor identifierVisitor) { final var columnId = identifierVisitor.visitUid(uid); return OnSourceIndexGenerator.IndexedColumn.of(columnId, false, false); } } - @Nonnull public static Builder newBuilder() { return new Builder(); } @@ -320,13 +305,10 @@ public static final class Builder { private SemanticAnalyzer semanticAnalyzer; - @Nonnull private final List keyColumns; - @Nonnull private final List valueColumns; - @Nonnull private final Map indexOptions; private boolean isUnique; @@ -345,85 +327,71 @@ private Builder() { this.indexOptions = new HashMap<>(); } - @Nonnull - public Builder setIndexName(@Nonnull final Identifier indexName) { + public Builder setIndexName(final Identifier indexName) { this.indexName = indexName; return this; } - @Nonnull - public Builder setIndexSource(@Nonnull final LogicalPlanFragment indexSource) { + public Builder setIndexSource(final LogicalPlanFragment indexSource) { this.indexSource = indexSource; return this; } - @Nonnull - public Builder setSemanticAnalyzer(@Nonnull final SemanticAnalyzer semanticAnalyzer) { + public Builder setSemanticAnalyzer(final SemanticAnalyzer semanticAnalyzer) { this.semanticAnalyzer = semanticAnalyzer; return this; } - @Nonnull - public Builder addKeyColumn(@Nonnull final IndexedColumn keyColumn) { + public Builder addKeyColumn(final IndexedColumn keyColumn) { keyColumns.add(keyColumn); return this; } - @Nonnull - public Builder addValueColumn(@Nonnull final IndexedColumn keyColumn) { + public Builder addValueColumn(final IndexedColumn keyColumn) { valueColumns.add(keyColumn); return this; } - @Nonnull public List getValueColumns() { return valueColumns; } - @Nonnull - public Builder addIndexOption(@Nonnull final String key, @Nonnull final String value) { + public Builder addIndexOption(final String key, final String value) { indexOptions.put(key, value); return this; } - @Nonnull - public Builder addAllIndexOptions(@Nonnull final Map indexOptions) { + public Builder addAllIndexOptions(final Map indexOptions) { this.indexOptions.putAll(indexOptions); return this; } - @Nonnull public Builder setUnique(boolean isUnique) { this.isUnique = isUnique; return this; } - @Nonnull public Builder setUseLegacyExtremum(boolean useLegacyExtremum) { this.useLegacyExtremum = useLegacyExtremum; return this; } - @Nonnull public Builder setUseNullableArrays(boolean useNullableArrays) { this.useNullableArrays = useNullableArrays; return this; } - @Nonnull public Builder setGenerateKeyValueExpressionWithEmptyKey(boolean generateKeyValueExpressionWithEmptyKey) { this.generateKeyValueExpressionWithEmptyKey = generateKeyValueExpressionWithEmptyKey; return this; } - @Nonnull public Builder setMetadataBuilder(final RecordLayerSchemaTemplate.Builder metadataBuilder) { this.metadataBuilder = metadataBuilder; return this; } - @Nonnull public OnSourceIndexGenerator build() { Assert.notNullUnchecked(indexName); Assert.notNullUnchecked(indexSource); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/package-info.java index 4542e54c515..a24fb3b7951 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/package-info.java @@ -22,4 +22,7 @@ * This package contains code responsible for creating index definitions from SQL. */ +@NullMarked package com.apple.foundationdb.relational.recordlayer.query.ddl; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/CompiledSqlFunction.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/CompiledSqlFunction.java index f38dc75efe7..4aae245b6e8 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/CompiledSqlFunction.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/CompiledSqlFunction.java @@ -45,12 +45,12 @@ import com.apple.foundationdb.relational.recordlayer.query.Literals; import com.apple.foundationdb.relational.util.Assert; import com.google.common.collect.Iterables; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.List; import java.util.Optional; +import static com.apple.foundationdb.record.query.plan.cascades.Quantifier.ForEach; + /** * This represents a compilable SQL function. If the function is a table function, it is modeled as a join between * the function body as defined by the user, and a constant row representing the list of arguments as given in the @@ -62,36 +62,31 @@ @SuppressWarnings("OptionalUsedAsFieldOrParameterType") public class CompiledSqlFunction extends UserDefinedFunction implements WithPlanGenerationSideEffects { - @Nonnull private final RelationalExpression body; - @Nonnull private final Optional parametersCorrelation; - @Nonnull private final Literals literals; - protected CompiledSqlFunction(@Nonnull final String functionName, @Nonnull final List parameterNames, - @Nonnull final List parameterTypes, - @Nonnull final List> parameterDefaults, - @Nonnull final Optional parametersCorrelation, - @Nonnull final RelationalExpression body, - @Nonnull final Literals literals) { + protected CompiledSqlFunction(final String functionName, final List parameterNames, + final List parameterTypes, + final List> parameterDefaults, + final Optional parametersCorrelation, + final RelationalExpression body, + final Literals literals) { super(functionName, parameterNames, parameterTypes, parameterDefaults); this.parametersCorrelation = parametersCorrelation; this.body = body; this.literals = literals; } - @Nonnull @Override public RecordMetaDataProto.PUserDefinedFunction toProto() { throw new RecordCoreException("attempt to serialize compiled SQL function"); } - @Nonnull @Override - public RelationalExpression encapsulate(@Nonnull final CallSiteArguments arguments) { + public RelationalExpression encapsulate(final CallSiteArguments arguments) { if (parametersCorrelation.isEmpty()) { // this should never happen. Assert.thatUnchecked(arguments.isEmpty(), ErrorCode.INTERNAL_ERROR, @@ -105,7 +100,7 @@ public RelationalExpression encapsulate(@Nonnull final CallSiteArguments argumen return encapsulateFromArgumentValues(resolveParameterValuesFromArguments(arguments.getArgumentsList())); } - private RelationalExpression encapsulateFromArgumentValues(@Nonnull final List resolvedArgumentValues) { + private RelationalExpression encapsulateFromArgumentValues(final List resolvedArgumentValues) { final var resultBuilder = GraphExpansion.builder(); for (var paramIdx = 0; paramIdx < getParameterNames().size(); paramIdx++) { resultBuilder.addResultColumn(Column.of( @@ -118,8 +113,7 @@ private RelationalExpression encapsulateFromArgumentValues(@Nonnull final List> parameterDefaults; - private final Quantifier.ForEach parametersQuantifier; + private final ForEach parametersQuantifier; private Literals literals; - CompiledSQLFunctionStepBuilder(@Nonnull final String name, - @Nonnull final RelationalExpression body, - @Nonnull final Expressions parameters, - @Nonnull final List> parameterDefaults, - @Nullable final Quantifier.ForEach parametersQuantifier, + CompiledSQLFunctionStepBuilder(final String name, + final RelationalExpression body, + final Expressions parameters, + final List> parameterDefaults, + @Nullable final ForEach parametersQuantifier, @Nullable final Type returnType) { Assert.isNullUnchecked(returnType, "unsupported explicit return type for compiled SQL function"); @@ -189,14 +178,12 @@ static final class CompiledSQLFunctionStepBuilder implements UserDefinedFunction this.literals = Literals.empty(); } - @Nonnull @Override - public UserDefinedFunctionBuilder.FinalStepBuilder setLiterals(@Nonnull final Literals literals) { + public UserDefinedFunctionBuilder.FinalStepBuilder setLiterals(final Literals literals) { this.literals = literals; return this; } - @Nonnull @Override public UserDefinedFunction build() { Assert.notNullUnchecked(name); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/SqlFunctionCatalog.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/SqlFunctionCatalog.java index 949c015d87d..447f9b242fa 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/SqlFunctionCatalog.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/SqlFunctionCatalog.java @@ -26,8 +26,6 @@ import com.apple.foundationdb.record.query.plan.cascades.values.RecordConstructorValue; import com.apple.foundationdb.record.query.plan.cascades.values.Value; import com.apple.foundationdb.relational.recordlayer.metadata.RecordLayerSchemaTemplate; - -import javax.annotation.Nonnull; import java.util.stream.StreamSupport; import static java.util.stream.Collectors.toList; @@ -45,8 +43,7 @@ public interface SqlFunctionCatalog { * @param arguments The arguments passed with the invocation of the function. * @return the function instance. */ - @Nonnull - CatalogedFunction lookupFunction(@Nonnull String name, @Nonnull CallSiteArguments arguments); + CatalogedFunction lookupFunction(String name, CallSiteArguments arguments); /** * Checks whether a function exists in the catalog. Note that invoking this method shall not trigger compiling @@ -54,10 +51,10 @@ public interface SqlFunctionCatalog { * @param name The name of the function. * @return {@code True} if the function exists, otherwise {@code false}. */ - boolean containsFunction(@Nonnull String name); + boolean containsFunction(String name); // TODO: this will be removed once we unify both Java- and SQL-UDFs. - boolean isJavaCallFunction(@Nonnull String name); + boolean isJavaCallFunction(String name); /** * Returns an instance of a {@link SqlFunctionCatalogImpl} with the following functions: @@ -73,8 +70,7 @@ public interface SqlFunctionCatalog { * * @return a new instance of {@link SqlFunctionCatalogImpl}. */ - @Nonnull - static SqlFunctionCatalog newInstance(@Nonnull final RecordLayerSchemaTemplate metadata, final boolean caseSensitive) { + static SqlFunctionCatalog newInstance(final RecordLayerSchemaTemplate metadata, final boolean caseSensitive) { return SqlFunctionCatalogImpl.newInstance(metadata, caseSensitive); } @@ -95,8 +91,7 @@ static SqlFunctionCatalog newInstance(@Nonnull final RecordLayerSchemaTemplate m * @return if the {@code value} is a single-item record, then the content of the {@code value} is recursively checked * and returned, otherwise, the {@code value} itself is returned without modification. */ - @Nonnull - static Typed flattenRecordWithOneField(@Nonnull final Typed value) { + static Typed flattenRecordWithOneField(final Typed value) { if (value instanceof RecordConstructorValue && ((RecordConstructorValue) value).getColumns().size() == 1) { return flattenRecordWithOneField(((Value) value).getChildren().iterator().next()); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/SqlFunctionCatalogImpl.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/SqlFunctionCatalogImpl.java index 7f4102035b6..d80fabf4e3b 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/SqlFunctionCatalogImpl.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/SqlFunctionCatalogImpl.java @@ -31,8 +31,6 @@ import com.apple.foundationdb.relational.recordlayer.metadata.RecordLayerSchemaTemplate; import com.apple.foundationdb.relational.util.Assert; import com.google.common.collect.ImmutableMap; - -import javax.annotation.Nonnull; import java.util.Locale; import java.util.Optional; import java.util.function.Function; @@ -43,19 +41,16 @@ @API(API.Status.EXPERIMENTAL) final class SqlFunctionCatalogImpl implements SqlFunctionCatalog { - @Nonnull private static final ImmutableMap>>> builtInSynonyms = createSynonyms(); - @Nonnull private final UserDefinedFunctionCatalog userDefinedFunctionCatalog; private SqlFunctionCatalogImpl(boolean isCaseSensitive) { this.userDefinedFunctionCatalog = new UserDefinedFunctionCatalog(isCaseSensitive); } - @Nonnull @Override - public CatalogedFunction lookupFunction(@Nonnull final String name, @Nonnull final CallSiteArguments arguments) { + public CatalogedFunction lookupFunction(final String name, final CallSiteArguments arguments) { final var builtInFunctionMaybe = lookupBuiltInFunction(name, arguments); final var userDefinedFunctionMaybe = lookupUserDefinedFunction(name, arguments); if (builtInFunctionMaybe.isPresent() && userDefinedFunctionMaybe.isPresent()) { @@ -71,9 +66,8 @@ public CatalogedFunction lookupFunction(@Nonnull final String name, @Nonnull fin return userDefinedFunctionMaybe.get(); } - @Nonnull - private Optional lookupBuiltInFunction(@Nonnull final String name, - @Nonnull final CallSiteArguments callSiteArguments) { + private Optional lookupBuiltInFunction(final String name, + final CallSiteArguments callSiteArguments) { final var functionValidator = builtInSynonyms.get(name.toLowerCase(Locale.ROOT)); if (functionValidator == null) { return Optional.empty(); @@ -82,29 +76,27 @@ private Optional lookupBuiltInFunction(@Nonnull fin return functionValidator.apply(callSiteArguments.size()); } - @Nonnull - private Optional lookupUserDefinedFunction(@Nonnull final String name, - @Nonnull final CallSiteArguments arguments) { + private Optional lookupUserDefinedFunction(final String name, + final CallSiteArguments arguments) { return userDefinedFunctionCatalog.lookup(name, arguments); } @Override - public boolean containsFunction(@Nonnull final String name) { + public boolean containsFunction(final String name) { return builtInSynonyms.containsKey(name.toLowerCase(Locale.ROOT)) || userDefinedFunctionCatalog.containsFunction(name); } @Override - public boolean isJavaCallFunction(@Nonnull final String name) { + public boolean isJavaCallFunction(final String name) { return "java_call".equals(name.trim().toLowerCase(Locale.ROOT)); } - public void registerUserDefinedFunction(@Nonnull final String functionName, - @Nonnull final Function functionSupplier) { + public void registerUserDefinedFunction(final String functionName, + final Function functionSupplier) { userDefinedFunctionCatalog.registerFunction(functionName, functionSupplier); } - @Nonnull private static ImmutableMap>>> createSynonyms() { return ImmutableMap.>>>builder() .put("+", argumentsCount -> BuiltInFunctionCatalog.resolve("add", argumentsCount)) @@ -161,8 +153,7 @@ private static ImmutableMap diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedFunctionBuilder.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedFunctionBuilder.java index 1ee5e742f26..86aeff1b18b 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedFunctionBuilder.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedFunctionBuilder.java @@ -38,9 +38,7 @@ import com.apple.foundationdb.relational.util.Assert; import com.google.common.collect.ImmutableList; import com.google.common.collect.Streams; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.List; import java.util.Optional; @@ -86,7 +84,7 @@ public interface SignatureStepBuilder { * @param name the function name. * @return this builder, for chaining. */ - SignatureStepBuilder setName(@Nonnull String name); + SignatureStepBuilder setName(String name); /** * Appends a single parameter to the signature. @@ -100,7 +98,7 @@ public interface SignatureStepBuilder { * @param expression the parameter to append. * @return this builder, for chaining. */ - SignatureStepBuilder addParameter(@Nonnull Expression expression); + SignatureStepBuilder addParameter(Expression expression); /** * Appends all the given parameters to the signature, preserving their order. @@ -114,7 +112,7 @@ public interface SignatureStepBuilder { * @param expressions the parameters to append. * @return this builder, for chaining. */ - SignatureStepBuilder addAllParameters(@Nonnull Expressions expressions); + SignatureStepBuilder addAllParameters(Expressions expressions); /** * Sets an explicit return type for the function; passing {@code null} leaves the return type to be inferred @@ -148,7 +146,7 @@ public interface BodyStepBuilder { * @param bodyExpression the relational expression the function evaluates to. * @return the final step, which builds a {@link CompiledSqlFunction}. */ - FinalStepBuilder withBodyExpression(@Nonnull RelationalExpression bodyExpression); + FinalStepBuilder withBodyExpression(RelationalExpression bodyExpression); /** * Supplies a {@link Value} as the function body, which returns a {@link FinalStepBuilder} that @@ -156,7 +154,7 @@ public interface BodyStepBuilder { * @param bodyValue the value the function evaluates to. * @return the final step, which builds a {@link UserDefinedMacroFunction}. */ - FinalStepBuilder withBodyValue(@Nonnull Value bodyValue); + FinalStepBuilder withBodyValue(Value bodyValue); } /** @@ -168,7 +166,7 @@ public interface FinalStepBuilder { * @param literals the literals to attach. * @return this builder, for chaining. */ - FinalStepBuilder setLiterals(@Nonnull Literals literals); + FinalStepBuilder setLiterals(Literals literals); /** * Builds the {@link UserDefinedFunction} from all the provided specifications. @@ -183,7 +181,6 @@ public interface FinalStepBuilder { * matches the chosen body kind. */ public static final class UserDefinedFunctionSignatureStepBuilder implements SignatureStepBuilder, BodyStepBuilder { - @Nonnull private final ImmutableList.Builder parametersBuilder; private String name; private Expressions parameters; @@ -195,19 +192,19 @@ private UserDefinedFunctionSignatureStepBuilder() { } @Override - public SignatureStepBuilder setName(@Nonnull final String name) { + public SignatureStepBuilder setName(final String name) { this.name = name; return this; } @Override - public SignatureStepBuilder addParameter(@Nonnull final Expression expression) { + public SignatureStepBuilder addParameter(final Expression expression) { parametersBuilder.add(expression.toNamedArgument()); return this; } @Override - public SignatureStepBuilder addAllParameters(@Nonnull final Expressions expressions) { + public SignatureStepBuilder addAllParameters(final Expressions expressions) { parametersBuilder.addAll(expressions.asNamedArguments()); return this; } @@ -248,7 +245,7 @@ public Optional getParametersCorrelation() { } @Override - public FinalStepBuilder withBodyExpression(@Nonnull final RelationalExpression bodyExpression) { + public FinalStepBuilder withBodyExpression(final RelationalExpression bodyExpression) { Assert.notNullUnchecked(name); Assert.notNullUnchecked(parameters); return new CompiledSqlFunction.CompiledSQLFunctionStepBuilder( @@ -256,7 +253,7 @@ public FinalStepBuilder withBodyExpression(@Nonnull final RelationalExpression b } @Override - public FinalStepBuilder withBodyValue(@Nonnull final Value bodyValue) { + public FinalStepBuilder withBodyValue(final Value bodyValue) { Assert.notNullUnchecked(name); Assert.notNullUnchecked(parameters); return new UserDefinedMacroFunctionBuilder(name, bodyValue, parameters, getParameterDefaultValues(), parametersQuantifier, returnType); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedFunctionCatalog.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedFunctionCatalog.java index 387812df260..4a5c6d7fba8 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedFunctionCatalog.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedFunctionCatalog.java @@ -23,8 +23,6 @@ import com.apple.foundationdb.record.query.plan.cascades.CallSiteArguments; import com.apple.foundationdb.record.query.plan.cascades.CatalogedFunction; import com.apple.foundationdb.record.query.plan.cascades.UserDefinedFunction; - -import javax.annotation.Nonnull; import java.util.LinkedHashMap; import java.util.Map; import java.util.Optional; @@ -32,7 +30,6 @@ final class UserDefinedFunctionCatalog { - @Nonnull private final Map> functionsMap; private final boolean isCaseSensitive; @@ -42,17 +39,16 @@ final class UserDefinedFunctionCatalog { this.functionsMap = new LinkedHashMap<>(); } - void registerFunction(@Nonnull final String functionName, - @Nonnull final Function function) { + void registerFunction(final String functionName, + final Function function) { functionsMap.put(functionName, function); } - public boolean containsFunction(@Nonnull final String name) { + public boolean containsFunction(final String name) { return functionsMap.containsKey(name); } - @Nonnull - public Optional lookup(@Nonnull final String functionName, @Nonnull final CallSiteArguments arguments) { + public Optional lookup(final String functionName, final CallSiteArguments arguments) { final var functionSupplier = functionsMap.get(functionName); if (functionSupplier == null) { return Optional.empty(); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedMacroFunctionBuilder.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedMacroFunctionBuilder.java index 2e06ad8aa72..83f56cbde46 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedMacroFunctionBuilder.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedMacroFunctionBuilder.java @@ -22,7 +22,6 @@ import com.apple.foundationdb.record.query.plan.cascades.Column; import com.apple.foundationdb.record.query.plan.cascades.CorrelationIdentifier; -import com.apple.foundationdb.record.query.plan.cascades.Quantifier; import com.apple.foundationdb.record.query.plan.cascades.UserDefinedFunction; import com.apple.foundationdb.record.query.plan.cascades.UserDefinedMacroFunction; import com.apple.foundationdb.record.query.plan.cascades.typing.Type; @@ -37,28 +36,23 @@ import com.apple.foundationdb.relational.recordlayer.query.Literals; import com.apple.foundationdb.relational.util.Assert; import com.google.common.collect.ImmutableList; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.List; import java.util.Optional; +import static com.apple.foundationdb.record.query.plan.cascades.Quantifier.ForEach; + /** * The {@link UserDefinedFunctionBuilder.FinalStepBuilder} that instantiates a {@link UserDefinedMacroFunction}. */ final class UserDefinedMacroFunctionBuilder implements UserDefinedFunctionBuilder.FinalStepBuilder { - @Nonnull private final String name; - @Nonnull private final Value bodyValue; - @Nonnull private final Expressions parameters; - @Nonnull private final List> parameterDefaults; @Nullable - private final Quantifier.ForEach parametersQuantifier; - @Nonnull + private final ForEach parametersQuantifier; private final List parametersQuantifiedObjectValues; @Nullable private final Type returnType; @@ -73,11 +67,11 @@ final class UserDefinedMacroFunctionBuilder implements UserDefinedFunctionBuilde * @param parametersQuantifier the quantifier the body's parameter references are correlated to, or {@code null} * when the function has no parameters. */ - UserDefinedMacroFunctionBuilder(@Nonnull final String name, - @Nonnull final Value bodyValue, - @Nonnull final Expressions parameters, - @Nonnull final List> parameterDefaults, - @Nullable final Quantifier.ForEach parametersQuantifier, + UserDefinedMacroFunctionBuilder(final String name, + final Value bodyValue, + final Expressions parameters, + final List> parameterDefaults, + @Nullable final ForEach parametersQuantifier, @Nullable final Type returnType) { this.name = name; this.bodyValue = bodyValue; @@ -94,7 +88,7 @@ final class UserDefinedMacroFunctionBuilder implements UserDefinedFunctionBuilde * @throws UnsupportedOperationException always. */ @Override - public UserDefinedFunctionBuilder.FinalStepBuilder setLiterals(@Nonnull final Literals literals) { + public UserDefinedFunctionBuilder.FinalStepBuilder setLiterals(final Literals literals) { throw new UnsupportedOperationException("macro functions don't support processed literals"); } @@ -107,7 +101,6 @@ public UserDefinedFunctionBuilder.FinalStepBuilder setLiterals(@Nonnull final Li *

* @return the constructed macro function. */ - @Nonnull @Override public UserDefinedFunction build() { Assert.notNullUnchecked(name); @@ -131,7 +124,6 @@ public UserDefinedFunction build() { * parameters; the unique aliases makes it possible to bind the parameters independently during encapsulation. * @return a quantified object value for each parameter, in declaration order. */ - @Nonnull private List computeParameterQuantifiedObjectValues() { ImmutableList.Builder quantifiedObjectValueBuilder = ImmutableList.builder(); for (var i = 0; i < parameters.size(); i++) { @@ -153,7 +145,7 @@ private List computeParameterQuantifiedObjectValues() { * @return a {@code Value} that is correlated to the provided quantified object values instead of * {@code this.parameterQuantifier}. */ - private Value translateBodyValueParametersCorrelations(@Nonnull final List parametersQuantifiedObjectValues) { + private Value translateBodyValueParametersCorrelations(final List parametersQuantifiedObjectValues) { if (parametersQuantifiedObjectValues.isEmpty()) { return bodyValue; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/WithPlanGenerationSideEffects.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/WithPlanGenerationSideEffects.java index f1b993e27c1..3e385c1cad8 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/WithPlanGenerationSideEffects.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/WithPlanGenerationSideEffects.java @@ -21,9 +21,6 @@ package com.apple.foundationdb.relational.recordlayer.query.functions; import com.apple.foundationdb.relational.recordlayer.query.Literals; - -import javax.annotation.Nonnull; - /** * Trait used to capture side effects resulting from the integration of a * {@link com.apple.foundationdb.record.query.plan.cascades.UserDefinedFunction} into a query plan. @@ -39,7 +36,6 @@ public interface WithPlanGenerationSideEffects { * Retrieve any extra literals that might have been either extracted away, or provided as a prepared parameter. * @return any extra function literals. */ - @Nonnull Literals getAuxiliaryLiterals(); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/package-info.java index 752a12556b3..2e0a5be2305 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/package-info.java @@ -22,4 +22,7 @@ * This package contains logic related to resolving builtin and user defined SQL functions. */ +@NullMarked package com.apple.foundationdb.relational.recordlayer.query.functions; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/package-info.java index 84433488aea..6da65fbf962 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/package-info.java @@ -22,4 +22,7 @@ * A RecordLayer-based implementation of a Relational query. */ +@NullMarked package com.apple.foundationdb.relational.recordlayer.query; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/BaseVisitor.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/BaseVisitor.java index 4a051d46bc1..3e80e83d5cb 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/BaseVisitor.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/BaseVisitor.java @@ -53,9 +53,7 @@ import com.apple.foundationdb.relational.recordlayer.query.functions.SqlFunctionCatalog; import com.apple.foundationdb.relational.util.Assert; import org.antlr.v4.runtime.tree.ParseTree; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.net.URI; import java.util.List; import java.util.Optional; @@ -71,51 +69,39 @@ public class BaseVisitor extends RelationalParserBaseVisitor implements private final boolean caseSensitive; - @Nonnull protected final MutablePlanGenerationContext mutablePlanGenerationContext; - @Nonnull private final DdlQueryFactory ddlQueryFactory; - @Nonnull private final URI dbUri; /** * The current plan fragment. This will initially be empty, prior to the first call to {@link #pushPlanFragment()}. */ - @Nonnull protected Optional currentPlanFragment; - @Nonnull private final ExpressionVisitor expressionVisitor; - @Nonnull private final IdentifierVisitor identifierVisitor; - @Nonnull private final QueryVisitor queryVisitor; - @Nonnull private final MetadataPlanVisitor metadataPlanVisitor; - @Nonnull private final DdlVisitor ddlVisitor; - @Nonnull private RecordLayerSchemaTemplate metadata; - @Nonnull private SemanticAnalyzer semanticAnalyzer; - @Nonnull private final LogicalOperatorCatalog logicalOperatorCatalog; @SuppressWarnings("this-escape") - public BaseVisitor(@Nonnull MutablePlanGenerationContext mutablePlanGenerationContext, - @Nonnull RecordLayerSchemaTemplate metadata, - @Nonnull DdlQueryFactory ddlQueryFactory, - @Nonnull MetadataOperationsFactory metadataOperationsFactory, - @Nonnull URI dbUri, + public BaseVisitor(MutablePlanGenerationContext mutablePlanGenerationContext, + RecordLayerSchemaTemplate metadata, + DdlQueryFactory ddlQueryFactory, + MetadataOperationsFactory metadataOperationsFactory, + URI dbUri, boolean caseSensitive) { this.mutablePlanGenerationContext = mutablePlanGenerationContext; this.metadata = metadata; @@ -133,47 +119,39 @@ public BaseVisitor(@Nonnull MutablePlanGenerationContext mutablePlanGenerationCo this.logicalOperatorCatalog = LogicalOperatorCatalog.newInstance(); } - @Nonnull public MutablePlanGenerationContext getPlanGenerationContext() { return mutablePlanGenerationContext; } - @Nonnull protected IdentifierVisitor getIdentifierVisitor() { return identifierVisitor; } - @Nonnull - public Plan generateLogicalPlan(@Nonnull ParseTree parseTree) { + public Plan generateLogicalPlan(ParseTree parseTree) { final var result = visit(parseTree); return Assert.castUnchecked(result, Plan.class, ErrorCode.INTERNAL_ERROR, () -> "Could not generate a logical plan"); } - @Nonnull public RecordLayerSchemaTemplate getSchemaTemplate() { return metadata; } - @Nonnull - public RecordLayerSchemaTemplate replaceSchemaTemplate(@Nonnull RecordLayerSchemaTemplate newCatalog) { + public RecordLayerSchemaTemplate replaceSchemaTemplate(RecordLayerSchemaTemplate newCatalog) { final var oldMetadata = metadata; metadata = newCatalog; semanticAnalyzer = new SemanticAnalyzer(metadata, createFunctionCatalog(metadata), mutablePlanGenerationContext, isCaseSensitive()); return oldMetadata; } - @Nonnull public SemanticAnalyzer getSemanticAnalyzer() { return semanticAnalyzer; } - @Nonnull public LogicalOperatorCatalog getLogicalOperatorCatalog() { return logicalOperatorCatalog; } - @Nonnull - public SqlFunctionCatalog createFunctionCatalog(@Nonnull final RecordLayerSchemaTemplate metadata) { + public SqlFunctionCatalog createFunctionCatalog(final RecordLayerSchemaTemplate metadata) { return SqlFunctionCatalog.newInstance(metadata, isCaseSensitive()); } @@ -181,12 +159,10 @@ public boolean isCaseSensitive() { return caseSensitive; } - @Nonnull LogicalOperators getLogicalOperators() { return currentPlanFragment.orElseThrow().getLogicalOperators(); } - @Nonnull LogicalOperators getLogicalOperatorsIncludingOuter() { return currentPlanFragment.orElseThrow().getLogicalOperatorsIncludingOuter(); } @@ -207,7 +183,6 @@ public boolean isTopLevel() { * * @see #popPlanFragment */ - @Nonnull public LogicalPlanFragment pushPlanFragment() { currentPlanFragment = Optional.of(currentPlanFragment.map(LogicalPlanFragment::addChild).orElse(LogicalPlanFragment.ofRoot())); return currentPlanFragment.get(); @@ -230,13 +205,11 @@ public void popPlanFragment() { * @throws com.apple.foundationdb.relational.api.exceptions.RelationalException if no fragment has been pushed * @see #pushPlanFragment */ - @Nonnull LogicalPlanFragment getCurrentPlanFragment() { Assert.thatUnchecked(currentPlanFragment.isPresent()); return currentPlanFragment.get(); } - @Nonnull Optional getCurrentPlanFragmentMaybe() { return currentPlanFragment; } @@ -245,29 +218,24 @@ boolean isForDdl() { return getPlanGenerationContext().isForDdl(); } - @Nonnull - protected String normalizeString(@Nonnull final String value) { + protected String normalizeString(final String value) { return Assert.notNullUnchecked(SemanticAnalyzer.normalizeString(value, caseSensitive)); } - @Nonnull - public Expression resolveFunction(@Nonnull String functionName, @Nonnull Expression... arguments) { + public Expression resolveFunction(String functionName, Expression... arguments) { return resolveFunction(functionName, Expressions.of(arguments)); } - @Nonnull - public Expression resolveFunction(@Nonnull String functionName, @Nonnull Expressions arguments) { + public Expression resolveFunction(String functionName, Expressions arguments) { return getSemanticAnalyzer().resolveFunction(functionName, arguments.toCallSiteArguments(true), true); } - @Nonnull - public Expression resolveFunction(@Nonnull String functionName, boolean flattenSingleItemRecords, @Nonnull Expression... arguments) { + public Expression resolveFunction(String functionName, boolean flattenSingleItemRecords, Expression... arguments) { return getSemanticAnalyzer().resolveFunction(functionName, Expressions.of(arguments).toCallSiteArguments(flattenSingleItemRecords), flattenSingleItemRecords); } - @Nonnull - public LogicalOperator resolveTableValuedFunction(@Nonnull Identifier functionName, @Nonnull Expressions arguments) { + public LogicalOperator resolveTableValuedFunction(Identifier functionName, Expressions arguments) { return getSemanticAnalyzer().resolveTableFunction(functionName, arguments, true); } @@ -276,175 +244,147 @@ protected Object aggregateResult(Object aggregate, Object nextResult) { return nextResult != null ? nextResult : aggregate; } - @Nonnull @Override - public Object visitRoot(@Nonnull RelationalParser.RootContext ctx) { + public Object visitRoot(RelationalParser.RootContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitStatements(@Nonnull RelationalParser.StatementsContext ctx) { + public Object visitStatements(RelationalParser.StatementsContext ctx) { return visitChildren(ctx); } @Nullable @Override - public Object visitStatement(@Nonnull RelationalParser.StatementContext ctx) { + public Object visitStatement(RelationalParser.StatementContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public QueryPlan.LogicalQueryPlan visitDmlStatement(@Nonnull RelationalParser.DmlStatementContext ctx) { + public QueryPlan.LogicalQueryPlan visitDmlStatement(RelationalParser.DmlStatementContext ctx) { return queryVisitor.visitDmlStatement(ctx); } - @Nonnull @Override public Object visitDdlStatement(RelationalParser.DdlStatementContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitTransactionStatement(@Nonnull RelationalParser.TransactionStatementContext ctx) { + public Object visitTransactionStatement(RelationalParser.TransactionStatementContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitPreparedStatement(@Nonnull RelationalParser.PreparedStatementContext ctx) { + public Object visitPreparedStatement(RelationalParser.PreparedStatementContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitAdministrationStatement(@Nonnull RelationalParser.AdministrationStatementContext ctx) { + public Object visitAdministrationStatement(RelationalParser.AdministrationStatementContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitUtilityStatement(@Nonnull RelationalParser.UtilityStatementContext ctx) { + public Object visitUtilityStatement(RelationalParser.UtilityStatementContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitTemplateClause(@Nonnull RelationalParser.TemplateClauseContext ctx) { + public Object visitTemplateClause(RelationalParser.TemplateClauseContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public ProceduralPlan visitCreateSchemaStatement(@Nonnull RelationalParser.CreateSchemaStatementContext ctx) { + public ProceduralPlan visitCreateSchemaStatement(RelationalParser.CreateSchemaStatementContext ctx) { return ddlVisitor.visitCreateSchemaStatement(ctx); } - @Nonnull @Override - public ProceduralPlan visitCreateSchemaTemplateStatement(@Nonnull RelationalParser.CreateSchemaTemplateStatementContext ctx) { + public ProceduralPlan visitCreateSchemaTemplateStatement(RelationalParser.CreateSchemaTemplateStatementContext ctx) { return ddlVisitor.visitCreateSchemaTemplateStatement(ctx); } - @Nonnull @Override - public ProceduralPlan visitCreateDatabaseStatement(@Nonnull RelationalParser.CreateDatabaseStatementContext ctx) { + public ProceduralPlan visitCreateDatabaseStatement(RelationalParser.CreateDatabaseStatementContext ctx) { return ddlVisitor.visitCreateDatabaseStatement(ctx); } - @Nonnull @Override - public Object visitOptionsClause(@Nonnull RelationalParser.OptionsClauseContext ctx) { + public Object visitOptionsClause(RelationalParser.OptionsClauseContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitOption(@Nonnull RelationalParser.OptionContext ctx) { + public Object visitOption(RelationalParser.OptionContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public ProceduralPlan visitDropDatabaseStatement(@Nonnull RelationalParser.DropDatabaseStatementContext ctx) { + public ProceduralPlan visitDropDatabaseStatement(RelationalParser.DropDatabaseStatementContext ctx) { return ddlVisitor.visitDropDatabaseStatement(ctx); } - @Nonnull @Override - public ProceduralPlan visitDropSchemaTemplateStatement(@Nonnull RelationalParser.DropSchemaTemplateStatementContext ctx) { + public ProceduralPlan visitDropSchemaTemplateStatement(RelationalParser.DropSchemaTemplateStatementContext ctx) { return ddlVisitor.visitDropSchemaTemplateStatement(ctx); } - @Nonnull @Override - public ProceduralPlan visitDropSchemaStatement(@Nonnull RelationalParser.DropSchemaStatementContext ctx) { + public ProceduralPlan visitDropSchemaStatement(RelationalParser.DropSchemaStatementContext ctx) { return ddlVisitor.visitDropSchemaStatement(ctx); } - @Nonnull @Override - public RecordLayerTable visitStructDefinition(@Nonnull RelationalParser.StructDefinitionContext ctx) { + public RecordLayerTable visitStructDefinition(RelationalParser.StructDefinitionContext ctx) { return ddlVisitor.visitStructDefinition(ctx); } - @Nonnull @Override - public RecordLayerTable visitTableDefinition(@Nonnull RelationalParser.TableDefinitionContext ctx) { + public RecordLayerTable visitTableDefinition(RelationalParser.TableDefinitionContext ctx) { return ddlVisitor.visitTableDefinition(ctx); } - @Nonnull @Override - public Object visitColumnDefinition(@Nonnull RelationalParser.ColumnDefinitionContext ctx) { + public Object visitColumnDefinition(RelationalParser.ColumnDefinitionContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public DataType visitFunctionColumnType(@Nonnull final RelationalParser.FunctionColumnTypeContext ctx) { + public DataType visitFunctionColumnType(final RelationalParser.FunctionColumnTypeContext ctx) { return ddlVisitor.visitFunctionColumnType(ctx); } - @Nonnull @Override - public Boolean visitNullColumnConstraint(@Nonnull RelationalParser.NullColumnConstraintContext ctx) { + public Boolean visitNullColumnConstraint(RelationalParser.NullColumnConstraintContext ctx) { return ddlVisitor.visitNullColumnConstraint(ctx); } - @Nonnull @Override - public Object visitPrimaryKeyDefinition(@Nonnull RelationalParser.PrimaryKeyDefinitionContext ctx) { + public Object visitPrimaryKeyDefinition(RelationalParser.PrimaryKeyDefinitionContext ctx) { return visitChildren(ctx); } - @Nonnull @Override public List visitFullIdList(RelationalParser.FullIdListContext ctx) { return identifierVisitor.visitFullIdList(ctx); } - @Nonnull @Override - public DataType.Named visitEnumDefinition(@Nonnull RelationalParser.EnumDefinitionContext ctx) { + public DataType.Named visitEnumDefinition(RelationalParser.EnumDefinitionContext ctx) { return ddlVisitor.visitEnumDefinition(ctx); } - @Nonnull @Override - public RecordLayerIndex visitIndexAsSelectDefinition(@Nonnull RelationalParser.IndexAsSelectDefinitionContext ctx) { + public RecordLayerIndex visitIndexAsSelectDefinition(RelationalParser.IndexAsSelectDefinitionContext ctx) { return ddlVisitor.visitIndexAsSelectDefinition(ctx); } - @Nonnull @Override - public RecordLayerIndex visitIndexOnSourceDefinition(@Nonnull RelationalParser.IndexOnSourceDefinitionContext ctx) { + public RecordLayerIndex visitIndexOnSourceDefinition(RelationalParser.IndexOnSourceDefinitionContext ctx) { return ddlVisitor.visitIndexOnSourceDefinition(ctx); } - @Nonnull @Override public RecordLayerIndex visitVectorIndexDefinition(final RelationalParser.VectorIndexDefinitionContext ctx) { return ddlVisitor.visitVectorIndexDefinition(ctx); @@ -485,9 +425,8 @@ public LogicalOperator visitStatementBody(final RelationalParser.StatementBodyCo return ddlVisitor.visitStatementBody(ctx); } - @Nonnull @Override - public Expression visitUserDefinedMacroFunctionStatementBody(@Nonnull RelationalParser.UserDefinedMacroFunctionStatementBodyContext ctx) { + public Expression visitUserDefinedMacroFunctionStatementBody(RelationalParser.UserDefinedMacroFunctionStatementBodyContext ctx) { return ddlVisitor.visitUserDefinedMacroFunctionStatementBody(ctx); } @@ -576,57 +515,48 @@ public Object visitDispatchClause(final RelationalParser.DispatchClauseContext c return visitChildren(ctx); } - @Nonnull @Override - public Object visitCharSet(@Nonnull RelationalParser.CharSetContext ctx) { + public Object visitCharSet(RelationalParser.CharSetContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitIntervalType(@Nonnull RelationalParser.IntervalTypeContext ctx) { + public Object visitIntervalType(RelationalParser.IntervalTypeContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitSchemaId(@Nonnull RelationalParser.SchemaIdContext ctx) { + public Object visitSchemaId(RelationalParser.SchemaIdContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitPath(@Nonnull RelationalParser.PathContext ctx) { + public Object visitPath(RelationalParser.PathContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitSchemaTemplateId(@Nonnull RelationalParser.SchemaTemplateIdContext ctx) { + public Object visitSchemaTemplateId(RelationalParser.SchemaTemplateIdContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public LogicalOperator visitDeleteStatement(@Nonnull RelationalParser.DeleteStatementContext ctx) { + public LogicalOperator visitDeleteStatement(RelationalParser.DeleteStatementContext ctx) { return queryVisitor.visitDeleteStatement(ctx); } - @Nonnull @Override - public LogicalOperator visitInsertStatement(@Nonnull RelationalParser.InsertStatementContext ctx) { + public LogicalOperator visitInsertStatement(RelationalParser.InsertStatementContext ctx) { return queryVisitor.visitInsertStatement(ctx); } - @Nonnull @Override public QueryPlan.LogicalQueryPlan visitSelectStatement(RelationalParser.SelectStatementContext ctx) { return queryVisitor.visitSelectStatement(ctx); } - @Nonnull @Override - public LogicalOperator visitQuery(@Nonnull RelationalParser.QueryContext ctx) { + public LogicalOperator visitQuery(RelationalParser.QueryContext ctx) { return queryVisitor.visitQuery(ctx); } @@ -636,14 +566,13 @@ public Void visitCtes(RelationalParser.CtesContext ctx) { return queryVisitor.visitCtes(ctx); } - @Nonnull @Override public LogicalOperator visitNamedQuery(RelationalParser.NamedQueryContext ctx) { return queryVisitor.visitNamedQuery(ctx); } @Override - public LogicalOperator visitTableFunction(@Nonnull final RelationalParser.TableFunctionContext ctx) { + public LogicalOperator visitTableFunction(final RelationalParser.TableFunctionContext ctx) { return expressionVisitor.visitTableFunction(ctx); } @@ -657,114 +586,98 @@ public Identifier visitTableFunctionName(final RelationalParser.TableFunctionNam return identifierVisitor.visitTableFunctionName(ctx); } - @Nonnull @Override - public Expression visitContinuationAtom(@Nonnull RelationalParser.ContinuationAtomContext ctx) { + public Expression visitContinuationAtom(RelationalParser.ContinuationAtomContext ctx) { return expressionVisitor.visitContinuationAtom(ctx); } - @Nonnull @Override - public LogicalOperator visitQueryTermDefault(@Nonnull RelationalParser.QueryTermDefaultContext ctx) { + public LogicalOperator visitQueryTermDefault(RelationalParser.QueryTermDefaultContext ctx) { return Assert.castUnchecked(visitChildren(ctx), LogicalOperator.class); } - @Nonnull @Override public LogicalOperator visitSetQuery(RelationalParser.SetQueryContext ctx) { return queryVisitor.visitSetQuery(ctx); } - @Nonnull @Override - public LogicalOperator visitInsertStatementValueSelect(@Nonnull RelationalParser.InsertStatementValueSelectContext ctx) { + public LogicalOperator visitInsertStatementValueSelect(RelationalParser.InsertStatementValueSelectContext ctx) { return queryVisitor.visitInsertStatementValueSelect(ctx); } - @Nonnull @Override - public LogicalOperator visitInsertStatementValueValues(@Nonnull RelationalParser.InsertStatementValueValuesContext ctx) { + public LogicalOperator visitInsertStatementValueValues(RelationalParser.InsertStatementValueValuesContext ctx) { return queryVisitor.visitInsertStatementValueValues(ctx); } - @Nonnull @Override - public Expressions visitUpdatedElement(@Nonnull RelationalParser.UpdatedElementContext ctx) { + public Expressions visitUpdatedElement(RelationalParser.UpdatedElementContext ctx) { return expressionVisitor.visitUpdatedElement(ctx); } - @Nonnull @Override - public Object visitAssignmentField(@Nonnull RelationalParser.AssignmentFieldContext ctx) { + public Object visitAssignmentField(RelationalParser.AssignmentFieldContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public LogicalOperator visitUpdateStatement(@Nonnull RelationalParser.UpdateStatementContext ctx) { + public LogicalOperator visitUpdateStatement(RelationalParser.UpdateStatementContext ctx) { return queryVisitor.visitUpdateStatement(ctx); } - @Nonnull @Override - public List visitOrderByClause(@Nonnull RelationalParser.OrderByClauseContext ctx) { + public List visitOrderByClause(RelationalParser.OrderByClauseContext ctx) { return expressionVisitor.visitOrderByClause(ctx); } - @Nonnull @Override - public OrderByExpression visitOrderByExpression(@Nonnull RelationalParser.OrderByExpressionContext ctx) { + public OrderByExpression visitOrderByExpression(RelationalParser.OrderByExpressionContext ctx) { return expressionVisitor.visitOrderByExpression(ctx); } @Override @Nullable - public Void visitTableSources(@Nonnull RelationalParser.TableSourcesContext ctx) { + public Void visitTableSources(RelationalParser.TableSourcesContext ctx) { return queryVisitor.visitTableSources(ctx); } @Nullable @Override - public Void visitTableSourceBase(@Nonnull RelationalParser.TableSourceBaseContext ctx) { + public Void visitTableSourceBase(RelationalParser.TableSourceBaseContext ctx) { return queryVisitor.visitTableSourceBase(ctx); } - @Nonnull @Override - public LogicalOperator visitAtomTableItem(@Nonnull RelationalParser.AtomTableItemContext ctx) { + public LogicalOperator visitAtomTableItem(RelationalParser.AtomTableItemContext ctx) { return queryVisitor.visitAtomTableItem(ctx); } - @Nonnull @Override - public LogicalOperator visitSubqueryTableItem(@Nonnull RelationalParser.SubqueryTableItemContext ctx) { + public LogicalOperator visitSubqueryTableItem(RelationalParser.SubqueryTableItemContext ctx) { return queryVisitor.visitSubqueryTableItem(ctx); } - @Nonnull @Override - public LogicalOperator visitInlineTableItem(@Nonnull RelationalParser.InlineTableItemContext ctx) { + public LogicalOperator visitInlineTableItem(RelationalParser.InlineTableItemContext ctx) { return queryVisitor.visitInlineTableItem(ctx); } @Override - public LogicalOperator visitTableValuedFunction(@Nonnull final RelationalParser.TableValuedFunctionContext ctx) { + public LogicalOperator visitTableValuedFunction(final RelationalParser.TableValuedFunctionContext ctx) { return queryVisitor.visitTableValuedFunction(ctx); } - @Nonnull @Override - public Set visitIndexHint(@Nonnull RelationalParser.IndexHintContext ctx) { + public Set visitIndexHint(RelationalParser.IndexHintContext ctx) { return queryVisitor.visitIndexHint(ctx); } - @Nonnull @Override - public Object visitIndexHintType(@Nonnull RelationalParser.IndexHintTypeContext ctx) { + public Object visitIndexHintType(RelationalParser.IndexHintTypeContext ctx) { return visitChildren(ctx); } - @Nonnull @Override public NonnullPair visitInlineTableDefinition(final RelationalParser.InlineTableDefinitionContext ctx) { return expressionVisitor.visitInlineTableDefinition(ctx); @@ -772,812 +685,681 @@ public NonnullPair @Nullable @Override - public Object visitInnerJoin(@Nonnull RelationalParser.InnerJoinContext ctx) { + public Object visitInnerJoin(RelationalParser.InnerJoinContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitStraightJoin(@Nonnull RelationalParser.StraightJoinContext ctx) { + public Object visitStraightJoin(RelationalParser.StraightJoinContext ctx) { throw new RelationalException("STRAIGHT_JOIN is not supported", ErrorCode.UNSUPPORTED_QUERY).toUncheckedWrappedException(); } - @Nonnull @Override - public Object visitOuterJoin(@Nonnull RelationalParser.OuterJoinContext ctx) { + public Object visitOuterJoin(RelationalParser.OuterJoinContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitNaturalJoin(@Nonnull RelationalParser.NaturalJoinContext ctx) { + public Object visitNaturalJoin(RelationalParser.NaturalJoinContext ctx) { throw new RelationalException("NATURAL JOIN is not supported", ErrorCode.UNSUPPORTED_QUERY).toUncheckedWrappedException(); } - @Nonnull @Override - public LogicalOperator visitSimpleTable(@Nonnull RelationalParser.SimpleTableContext ctx) { + public LogicalOperator visitSimpleTable(RelationalParser.SimpleTableContext ctx) { return queryVisitor.visitSimpleTable(ctx); } - @Nonnull @Override public LogicalOperator visitParenthesisQuery(RelationalParser.ParenthesisQueryContext ctx) { return queryVisitor.visitParenthesisQuery(ctx); } - @Nonnull @Override - public Expressions visitSelectElements(@Nonnull RelationalParser.SelectElementsContext ctx) { + public Expressions visitSelectElements(RelationalParser.SelectElementsContext ctx) { return expressionVisitor.visitSelectElements(ctx); } - @Nonnull @Override - public Expression visitSelectStarElement(@Nonnull RelationalParser.SelectStarElementContext ctx) { + public Expression visitSelectStarElement(RelationalParser.SelectStarElementContext ctx) { return expressionVisitor.visitSelectStarElement(ctx); } - @Nonnull @Override - public Object visitSelectQualifierStarElement(@Nonnull RelationalParser.SelectQualifierStarElementContext ctx) { + public Object visitSelectQualifierStarElement(RelationalParser.SelectQualifierStarElementContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Expression visitSelectExpressionElement(@Nonnull RelationalParser.SelectExpressionElementContext ctx) { + public Expression visitSelectExpressionElement(RelationalParser.SelectExpressionElementContext ctx) { return expressionVisitor.visitSelectExpressionElement(ctx); } @Override @Nullable - public Void visitFromClause(@Nonnull RelationalParser.FromClauseContext ctx) { + public Void visitFromClause(RelationalParser.FromClauseContext ctx) { return queryVisitor.visitFromClause(ctx); } - @Nonnull @Override - public Expressions visitGroupByClause(@Nonnull RelationalParser.GroupByClauseContext ctx) { + public Expressions visitGroupByClause(RelationalParser.GroupByClauseContext ctx) { return expressionVisitor.visitGroupByClause(ctx); } - @Nonnull @Override - public Expression visitWhereExpr(@Nonnull RelationalParser.WhereExprContext ctx) { + public Expression visitWhereExpr(RelationalParser.WhereExprContext ctx) { return expressionVisitor.visitWhereExpr(ctx); } - @Nonnull @Override - public Expression visitHavingClause(@Nonnull RelationalParser.HavingClauseContext ctx) { + public Expression visitHavingClause(RelationalParser.HavingClauseContext ctx) { return expressionVisitor.visitHavingClause(ctx); } - @Nonnull @Override public Expression visitQualifyClause(final RelationalParser.QualifyClauseContext ctx) { return expressionVisitor.visitQualifyClause(ctx); } - @Nonnull @Override - public Expression visitGroupByItem(@Nonnull RelationalParser.GroupByItemContext ctx) { + public Expression visitGroupByItem(RelationalParser.GroupByItemContext ctx) { return expressionVisitor.visitGroupByItem(ctx); } - @Nonnull @Override - public Expression visitLimitClause(@Nonnull RelationalParser.LimitClauseContext ctx) { + public Expression visitLimitClause(RelationalParser.LimitClauseContext ctx) { return expressionVisitor.visitLimitClause(ctx); } - @Nonnull @Override - public Expression visitLimitClauseAtom(@Nonnull RelationalParser.LimitClauseAtomContext ctx) { + public Expression visitLimitClauseAtom(RelationalParser.LimitClauseAtomContext ctx) { return expressionVisitor.visitLimitClauseAtom(ctx); } - @Nonnull @Override - public Object visitStatementOptions(@Nonnull RelationalParser.StatementOptionsContext ctx) { + public Object visitStatementOptions(RelationalParser.StatementOptionsContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitStatementOption(@Nonnull RelationalParser.StatementOptionContext ctx) { + public Object visitStatementOption(RelationalParser.StatementOptionContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitStartTransaction(@Nonnull RelationalParser.StartTransactionContext ctx) { + public Object visitStartTransaction(RelationalParser.StartTransactionContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitCommitStatement(@Nonnull RelationalParser.CommitStatementContext ctx) { + public Object visitCommitStatement(RelationalParser.CommitStatementContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitRollbackStatement(@Nonnull RelationalParser.RollbackStatementContext ctx) { + public Object visitRollbackStatement(RelationalParser.RollbackStatementContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitSetAutocommitStatement(@Nonnull RelationalParser.SetAutocommitStatementContext ctx) { + public Object visitSetAutocommitStatement(RelationalParser.SetAutocommitStatementContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitSetTransactionStatement(@Nonnull RelationalParser.SetTransactionStatementContext ctx) { + public Object visitSetTransactionStatement(RelationalParser.SetTransactionStatementContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitTransactionOption(@Nonnull RelationalParser.TransactionOptionContext ctx) { + public Object visitTransactionOption(RelationalParser.TransactionOptionContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitTransactionLevel(@Nonnull RelationalParser.TransactionLevelContext ctx) { + public Object visitTransactionLevel(RelationalParser.TransactionLevelContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitPrepareStatement(@Nonnull RelationalParser.PrepareStatementContext ctx) { + public Object visitPrepareStatement(RelationalParser.PrepareStatementContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitExecuteStatement(@Nonnull RelationalParser.ExecuteStatementContext ctx) { + public Object visitExecuteStatement(RelationalParser.ExecuteStatementContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public QueryPlan.MetadataQueryPlan visitShowDatabasesStatement(@Nonnull RelationalParser.ShowDatabasesStatementContext ctx) { + public QueryPlan.MetadataQueryPlan visitShowDatabasesStatement(RelationalParser.ShowDatabasesStatementContext ctx) { return metadataPlanVisitor.visitShowDatabasesStatement(ctx); } - @Nonnull @Override - public QueryPlan.MetadataQueryPlan visitShowSchemaTemplatesStatement(@Nonnull RelationalParser.ShowSchemaTemplatesStatementContext ctx) { + public QueryPlan.MetadataQueryPlan visitShowSchemaTemplatesStatement(RelationalParser.ShowSchemaTemplatesStatementContext ctx) { return metadataPlanVisitor.visitShowSchemaTemplatesStatement(ctx); } - @Nonnull @Override - public Object visitSetVariable(@Nonnull RelationalParser.SetVariableContext ctx) { + public Object visitSetVariable(RelationalParser.SetVariableContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitSetCharset(@Nonnull RelationalParser.SetCharsetContext ctx) { + public Object visitSetCharset(RelationalParser.SetCharsetContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitSetNames(@Nonnull RelationalParser.SetNamesContext ctx) { + public Object visitSetNames(RelationalParser.SetNamesContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitSetTransaction(@Nonnull RelationalParser.SetTransactionContext ctx) { + public Object visitSetTransaction(RelationalParser.SetTransactionContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitSetAutocommit(@Nonnull RelationalParser.SetAutocommitContext ctx) { + public Object visitSetAutocommit(RelationalParser.SetAutocommitContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitSetNewValueInsideTrigger(@Nonnull RelationalParser.SetNewValueInsideTriggerContext ctx) { + public Object visitSetNewValueInsideTrigger(RelationalParser.SetNewValueInsideTriggerContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitVariableClause(@Nonnull RelationalParser.VariableClauseContext ctx) { + public Object visitVariableClause(RelationalParser.VariableClauseContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitKillStatement(@Nonnull RelationalParser.KillStatementContext ctx) { + public Object visitKillStatement(RelationalParser.KillStatementContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitResetStatement(@Nonnull RelationalParser.ResetStatementContext ctx) { + public Object visitResetStatement(RelationalParser.ResetStatementContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitTableIndexes(@Nonnull RelationalParser.TableIndexesContext ctx) { + public Object visitTableIndexes(RelationalParser.TableIndexesContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitLoadedTableIndexes(@Nonnull RelationalParser.LoadedTableIndexesContext ctx) { + public Object visitLoadedTableIndexes(RelationalParser.LoadedTableIndexesContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public QueryPlan.MetadataQueryPlan visitSimpleDescribeSchemaStatement(@Nonnull RelationalParser.SimpleDescribeSchemaStatementContext ctx) { + public QueryPlan.MetadataQueryPlan visitSimpleDescribeSchemaStatement(RelationalParser.SimpleDescribeSchemaStatementContext ctx) { return metadataPlanVisitor.visitSimpleDescribeSchemaStatement(ctx); } - @Nonnull @Override - public QueryPlan.MetadataQueryPlan visitSimpleDescribeSchemaTemplateStatement(@Nonnull RelationalParser.SimpleDescribeSchemaTemplateStatementContext ctx) { + public QueryPlan.MetadataQueryPlan visitSimpleDescribeSchemaTemplateStatement(RelationalParser.SimpleDescribeSchemaTemplateStatementContext ctx) { return metadataPlanVisitor.visitSimpleDescribeSchemaTemplateStatement(ctx); } - @Nonnull @Override - public QueryPlan.LogicalQueryPlan visitFullDescribeStatement(@Nonnull RelationalParser.FullDescribeStatementContext ctx) { + public QueryPlan.LogicalQueryPlan visitFullDescribeStatement(RelationalParser.FullDescribeStatementContext ctx) { return queryVisitor.visitFullDescribeStatement(ctx); } - @Nonnull @Override - public Object visitHelpStatement(@Nonnull RelationalParser.HelpStatementContext ctx) { + public Object visitHelpStatement(RelationalParser.HelpStatementContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitDescribeStatements(@Nonnull RelationalParser.DescribeStatementsContext ctx) { + public Object visitDescribeStatements(RelationalParser.DescribeStatementsContext ctx) { return queryVisitor.visitDescribeStatements(ctx); } - @Nonnull @Override - public Object visitDescribeConnection(@Nonnull RelationalParser.DescribeConnectionContext ctx) { + public Object visitDescribeConnection(RelationalParser.DescribeConnectionContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Identifier visitFullId(@Nonnull RelationalParser.FullIdContext ctx) { + public Identifier visitFullId(RelationalParser.FullIdContext ctx) { return identifierVisitor.visitFullId(ctx); } - @Nonnull @Override - public Identifier visitTableName(@Nonnull RelationalParser.TableNameContext ctx) { + public Identifier visitTableName(RelationalParser.TableNameContext ctx) { return identifierVisitor.visitTableName(ctx); } - @Nonnull @Override - public Expression visitFullColumnName(@Nonnull RelationalParser.FullColumnNameContext ctx) { + public Expression visitFullColumnName(RelationalParser.FullColumnNameContext ctx) { return expressionVisitor.visitFullColumnName(ctx); } - @Nonnull @Override - public Identifier visitIndexColumnName(@Nonnull RelationalParser.IndexColumnNameContext ctx) { + public Identifier visitIndexColumnName(RelationalParser.IndexColumnNameContext ctx) { return identifierVisitor.visitIndexColumnName(ctx); } - @Nonnull @Override - public Identifier visitCharsetName(@Nonnull RelationalParser.CharsetNameContext ctx) { + public Identifier visitCharsetName(RelationalParser.CharsetNameContext ctx) { return identifierVisitor.visitCharsetName(ctx); } - @Nonnull @Override - public Identifier visitCollationName(@Nonnull RelationalParser.CollationNameContext ctx) { + public Identifier visitCollationName(RelationalParser.CollationNameContext ctx) { return identifierVisitor.visitCollationName(ctx); } - @Nonnull @Override - public Identifier visitUid(@Nonnull RelationalParser.UidContext ctx) { + public Identifier visitUid(RelationalParser.UidContext ctx) { return identifierVisitor.visitUid(ctx); } - @Nonnull @Override - public Identifier visitSimpleId(@Nonnull RelationalParser.SimpleIdContext ctx) { + public Identifier visitSimpleId(RelationalParser.SimpleIdContext ctx) { return identifierVisitor.visitSimpleId(ctx); } - @Nonnull @Override - public Object visitNullNotnull(@Nonnull RelationalParser.NullNotnullContext ctx) { + public Object visitNullNotnull(RelationalParser.NullNotnullContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Expression visitDecimalLiteral(@Nonnull RelationalParser.DecimalLiteralContext ctx) { + public Expression visitDecimalLiteral(RelationalParser.DecimalLiteralContext ctx) { return expressionVisitor.visitDecimalLiteral(ctx); } - @Nonnull @Override - public Expression visitStringLiteral(@Nonnull RelationalParser.StringLiteralContext ctx) { + public Expression visitStringLiteral(RelationalParser.StringLiteralContext ctx) { return expressionVisitor.visitStringLiteral(ctx); } - @Nonnull @Override - public Expression visitBooleanLiteral(@Nonnull RelationalParser.BooleanLiteralContext ctx) { + public Expression visitBooleanLiteral(RelationalParser.BooleanLiteralContext ctx) { return expressionVisitor.visitBooleanLiteral(ctx); } - @Nonnull @Override - public Expression visitBytesLiteral(@Nonnull RelationalParser.BytesLiteralContext ctx) { + public Expression visitBytesLiteral(RelationalParser.BytesLiteralContext ctx) { return expressionVisitor.visitBytesLiteral(ctx); } - @Nonnull @Override - public Expression visitNullLiteral(@Nonnull RelationalParser.NullLiteralContext ctx) { + public Expression visitNullLiteral(RelationalParser.NullLiteralContext ctx) { return expressionVisitor.visitNullLiteral(ctx); } - @Nonnull @Override - public Expression visitStringConstant(@Nonnull RelationalParser.StringConstantContext ctx) { + public Expression visitStringConstant(RelationalParser.StringConstantContext ctx) { return expressionVisitor.visitStringConstant(ctx); } - @Nonnull @Override - public Expression visitDecimalConstant(@Nonnull RelationalParser.DecimalConstantContext ctx) { + public Expression visitDecimalConstant(RelationalParser.DecimalConstantContext ctx) { return expressionVisitor.visitDecimalConstant(ctx); } - @Nonnull @Override - public Expression visitNegativeDecimalConstant(@Nonnull RelationalParser.NegativeDecimalConstantContext ctx) { + public Expression visitNegativeDecimalConstant(RelationalParser.NegativeDecimalConstantContext ctx) { return expressionVisitor.visitNegativeDecimalConstant(ctx); } - @Nonnull @Override - public Expression visitBytesConstant(@Nonnull RelationalParser.BytesConstantContext ctx) { + public Expression visitBytesConstant(RelationalParser.BytesConstantContext ctx) { return expressionVisitor.visitBytesConstant(ctx); } - @Nonnull @Override - public Expression visitBooleanConstant(@Nonnull RelationalParser.BooleanConstantContext ctx) { + public Expression visitBooleanConstant(RelationalParser.BooleanConstantContext ctx) { return expressionVisitor.visitBooleanConstant(ctx); } - @Nonnull @Override - public Expression visitBitStringConstant(@Nonnull RelationalParser.BitStringConstantContext ctx) { + public Expression visitBitStringConstant(RelationalParser.BitStringConstantContext ctx) { return expressionVisitor.visitBitStringConstant(ctx); } - @Nonnull @Override - public Expression visitNullConstant(@Nonnull RelationalParser.NullConstantContext ctx) { + public Expression visitNullConstant(RelationalParser.NullConstantContext ctx) { return expressionVisitor.visitNullConstant(ctx); } - @Nonnull @Override - public Object visitStringDataType(@Nonnull RelationalParser.StringDataTypeContext ctx) { + public Object visitStringDataType(RelationalParser.StringDataTypeContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitNationalStringDataType(@Nonnull RelationalParser.NationalStringDataTypeContext ctx) { + public Object visitNationalStringDataType(RelationalParser.NationalStringDataTypeContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitNationalVaryingStringDataType(@Nonnull RelationalParser.NationalVaryingStringDataTypeContext ctx) { + public Object visitNationalVaryingStringDataType(RelationalParser.NationalVaryingStringDataTypeContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitDimensionDataType(@Nonnull RelationalParser.DimensionDataTypeContext ctx) { + public Object visitDimensionDataType(RelationalParser.DimensionDataTypeContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitSimpleDataType(@Nonnull RelationalParser.SimpleDataTypeContext ctx) { + public Object visitSimpleDataType(RelationalParser.SimpleDataTypeContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitCollectionDataType(@Nonnull RelationalParser.CollectionDataTypeContext ctx) { + public Object visitCollectionDataType(RelationalParser.CollectionDataTypeContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitSpatialDataType(@Nonnull RelationalParser.SpatialDataTypeContext ctx) { + public Object visitSpatialDataType(RelationalParser.SpatialDataTypeContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitLongVarcharDataType(@Nonnull RelationalParser.LongVarcharDataTypeContext ctx) { + public Object visitLongVarcharDataType(RelationalParser.LongVarcharDataTypeContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitLongVarbinaryDataType(@Nonnull RelationalParser.LongVarbinaryDataTypeContext ctx) { + public Object visitLongVarbinaryDataType(RelationalParser.LongVarbinaryDataTypeContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitCollectionOptions(@Nonnull RelationalParser.CollectionOptionsContext ctx) { + public Object visitCollectionOptions(RelationalParser.CollectionOptionsContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitConvertedDataType(@Nonnull RelationalParser.ConvertedDataTypeContext ctx) { + public Object visitConvertedDataType(RelationalParser.ConvertedDataTypeContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitLengthOneDimension(@Nonnull RelationalParser.LengthOneDimensionContext ctx) { + public Object visitLengthOneDimension(RelationalParser.LengthOneDimensionContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitLengthTwoDimension(@Nonnull RelationalParser.LengthTwoDimensionContext ctx) { + public Object visitLengthTwoDimension(RelationalParser.LengthTwoDimensionContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitLengthTwoOptionalDimension(@Nonnull RelationalParser.LengthTwoOptionalDimensionContext ctx) { + public Object visitLengthTwoOptionalDimension(RelationalParser.LengthTwoOptionalDimensionContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public List visitUidList(@Nonnull RelationalParser.UidListContext ctx) { + public List visitUidList(RelationalParser.UidListContext ctx) { return identifierVisitor.visitUidList(ctx); } - @Nonnull @Override - public Object visitUidWithNestings(@Nonnull RelationalParser.UidWithNestingsContext ctx) { + public Object visitUidWithNestings(RelationalParser.UidWithNestingsContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public CompatibleTypeEvolutionPredicate.FieldAccessTrieNode visitUidListWithNestingsInParens(@Nonnull RelationalParser.UidListWithNestingsInParensContext ctx) { + public CompatibleTypeEvolutionPredicate.FieldAccessTrieNode visitUidListWithNestingsInParens(RelationalParser.UidListWithNestingsInParensContext ctx) { return expressionVisitor.visitUidListWithNestingsInParens(ctx); } - @Nonnull @Override - public CompatibleTypeEvolutionPredicate.FieldAccessTrieNode visitUidListWithNestings(@Nonnull RelationalParser.UidListWithNestingsContext ctx) { + public CompatibleTypeEvolutionPredicate.FieldAccessTrieNode visitUidListWithNestings(RelationalParser.UidListWithNestingsContext ctx) { return expressionVisitor.visitUidListWithNestings(ctx); } - @Nonnull @Override - public Object visitTables(@Nonnull RelationalParser.TablesContext ctx) { + public Object visitTables(RelationalParser.TablesContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitIndexColumnNames(@Nonnull RelationalParser.IndexColumnNamesContext ctx) { + public Object visitIndexColumnNames(RelationalParser.IndexColumnNamesContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Expressions visitExpressions(@Nonnull RelationalParser.ExpressionsContext ctx) { + public Expressions visitExpressions(RelationalParser.ExpressionsContext ctx) { return expressionVisitor.visitExpressions(ctx); } - @Nonnull @Override - public Object visitExpressionsWithDefaults(@Nonnull RelationalParser.ExpressionsWithDefaultsContext ctx) { + public Object visitExpressionsWithDefaults(RelationalParser.ExpressionsWithDefaultsContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Expression visitRecordConstructorForInsert(@Nonnull RelationalParser.RecordConstructorForInsertContext ctx) { + public Expression visitRecordConstructorForInsert(RelationalParser.RecordConstructorForInsertContext ctx) { return expressionVisitor.visitRecordConstructorForInsert(ctx); } - @Nonnull @Override public Expression visitRecordConstructorForInlineTable(final RelationalParser.RecordConstructorForInlineTableContext ctx) { return expressionVisitor.visitRecordConstructorForInlineTable(ctx); } - @Nonnull @Override - public Expression visitRecordConstructor(@Nonnull RelationalParser.RecordConstructorContext ctx) { + public Expression visitRecordConstructor(RelationalParser.RecordConstructorContext ctx) { return expressionVisitor.visitRecordConstructor(ctx); } - @Nonnull @Override - public Object visitOfTypeClause(@Nonnull RelationalParser.OfTypeClauseContext ctx) { + public Object visitOfTypeClause(RelationalParser.OfTypeClauseContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Expression visitArrayConstructor(@Nonnull RelationalParser.ArrayConstructorContext ctx) { + public Expression visitArrayConstructor(RelationalParser.ArrayConstructorContext ctx) { return expressionVisitor.visitArrayConstructor(ctx); } - @Nonnull @Override - public Object visitUserVariables(@Nonnull RelationalParser.UserVariablesContext ctx) { + public Object visitUserVariables(RelationalParser.UserVariablesContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitDefaultValue(@Nonnull RelationalParser.DefaultValueContext ctx) { + public Object visitDefaultValue(RelationalParser.DefaultValueContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitCurrentTimestamp(@Nonnull RelationalParser.CurrentTimestampContext ctx) { + public Object visitCurrentTimestamp(RelationalParser.CurrentTimestampContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitExpressionOrDefault(@Nonnull RelationalParser.ExpressionOrDefaultContext ctx) { + public Object visitExpressionOrDefault(RelationalParser.ExpressionOrDefaultContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Expression visitExpressionWithOptionalName(@Nonnull RelationalParser.ExpressionWithOptionalNameContext ctx) { + public Expression visitExpressionWithOptionalName(RelationalParser.ExpressionWithOptionalNameContext ctx) { return expressionVisitor.visitExpressionWithOptionalName(ctx); } @Nullable @Override - public Object visitIfExists(@Nonnull RelationalParser.IfExistsContext ctx) { + public Object visitIfExists(RelationalParser.IfExistsContext ctx) { return visitChildren(ctx); } @Nullable @Override - public Object visitIfNotExists(@Nonnull RelationalParser.IfNotExistsContext ctx) { + public Object visitIfNotExists(RelationalParser.IfNotExistsContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Expression visitAggregateFunctionCall(@Nonnull RelationalParser.AggregateFunctionCallContext ctx) { + public Expression visitAggregateFunctionCall(RelationalParser.AggregateFunctionCallContext ctx) { return expressionVisitor.visitAggregateFunctionCall(ctx); } - @Nonnull @Override - public Object visitSpecificFunctionCall(@Nonnull RelationalParser.SpecificFunctionCallContext ctx) { + public Object visitSpecificFunctionCall(RelationalParser.SpecificFunctionCallContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Expression visitScalarFunctionCall(@Nonnull RelationalParser.ScalarFunctionCallContext ctx) { + public Expression visitScalarFunctionCall(RelationalParser.ScalarFunctionCallContext ctx) { return expressionVisitor.visitScalarFunctionCall(ctx); } - @Nonnull @Override - public Expression visitUserDefinedScalarFunctionCall(@Nonnull RelationalParser.UserDefinedScalarFunctionCallContext ctx) { + public Expression visitUserDefinedScalarFunctionCall(RelationalParser.UserDefinedScalarFunctionCallContext ctx) { return expressionVisitor.visitUserDefinedScalarFunctionCall(ctx); } - @Nonnull @Override - public Object visitSimpleFunctionCall(@Nonnull RelationalParser.SimpleFunctionCallContext ctx) { + public Object visitSimpleFunctionCall(RelationalParser.SimpleFunctionCallContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitDataTypeFunctionCall(@Nonnull RelationalParser.DataTypeFunctionCallContext ctx) { + public Object visitDataTypeFunctionCall(RelationalParser.DataTypeFunctionCallContext ctx) { return expressionVisitor.visitDataTypeFunctionCall(ctx); } - @Nonnull @Override - public Object visitValuesFunctionCall(@Nonnull RelationalParser.ValuesFunctionCallContext ctx) { + public Object visitValuesFunctionCall(RelationalParser.ValuesFunctionCallContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitCaseExpressionFunctionCall(@Nonnull RelationalParser.CaseExpressionFunctionCallContext ctx) { + public Object visitCaseExpressionFunctionCall(RelationalParser.CaseExpressionFunctionCallContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Expression visitCaseFunctionCall(@Nonnull RelationalParser.CaseFunctionCallContext ctx) { + public Expression visitCaseFunctionCall(RelationalParser.CaseFunctionCallContext ctx) { return expressionVisitor.visitCaseFunctionCall(ctx); } - @Nonnull @Override - public Object visitCharFunctionCall(@Nonnull RelationalParser.CharFunctionCallContext ctx) { + public Object visitCharFunctionCall(RelationalParser.CharFunctionCallContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitPositionFunctionCall(@Nonnull RelationalParser.PositionFunctionCallContext ctx) { + public Object visitPositionFunctionCall(RelationalParser.PositionFunctionCallContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitSubstrFunctionCall(@Nonnull RelationalParser.SubstrFunctionCallContext ctx) { + public Object visitSubstrFunctionCall(RelationalParser.SubstrFunctionCallContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitTrimFunctionCall(@Nonnull RelationalParser.TrimFunctionCallContext ctx) { + public Object visitTrimFunctionCall(RelationalParser.TrimFunctionCallContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitWeightFunctionCall(@Nonnull RelationalParser.WeightFunctionCallContext ctx) { + public Object visitWeightFunctionCall(RelationalParser.WeightFunctionCallContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitExtractFunctionCall(@Nonnull RelationalParser.ExtractFunctionCallContext ctx) { + public Object visitExtractFunctionCall(RelationalParser.ExtractFunctionCallContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitGetFormatFunctionCall(@Nonnull RelationalParser.GetFormatFunctionCallContext ctx) { + public Object visitGetFormatFunctionCall(RelationalParser.GetFormatFunctionCallContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitCaseFuncAlternative(@Nonnull RelationalParser.CaseFuncAlternativeContext ctx) { + public Object visitCaseFuncAlternative(RelationalParser.CaseFuncAlternativeContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitLevelWeightList(@Nonnull RelationalParser.LevelWeightListContext ctx) { + public Object visitLevelWeightList(RelationalParser.LevelWeightListContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitLevelWeightRange(@Nonnull RelationalParser.LevelWeightRangeContext ctx) { + public Object visitLevelWeightRange(RelationalParser.LevelWeightRangeContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitLevelInWeightListElement(@Nonnull RelationalParser.LevelInWeightListElementContext ctx) { + public Object visitLevelInWeightListElement(RelationalParser.LevelInWeightListElementContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Expression visitAggregateWindowedFunction(@Nonnull RelationalParser.AggregateWindowedFunctionContext ctx) { + public Expression visitAggregateWindowedFunction(RelationalParser.AggregateWindowedFunctionContext ctx) { return expressionVisitor.visitAggregateWindowedFunction(ctx); } - @Nonnull @Override - public Boolean visitNullTreatmentClause(@Nonnull RelationalParser.NullTreatmentClauseContext ctx) { + public Boolean visitNullTreatmentClause(RelationalParser.NullTreatmentClauseContext ctx) { return expressionVisitor.visitNullTreatmentClause(ctx); } - @Nonnull @Override public Expression visitNonAggregateFunctionCall(final RelationalParser.NonAggregateFunctionCallContext ctx) { return expressionVisitor.visitNonAggregateFunctionCall(ctx); } - @Nonnull @Override - public Expression visitNonAggregateWindowedFunction(@Nonnull RelationalParser.NonAggregateWindowedFunctionContext ctx) { + public Expression visitNonAggregateWindowedFunction(RelationalParser.NonAggregateWindowedFunctionContext ctx) { return expressionVisitor.visitNonAggregateWindowedFunction(ctx); } - @Nonnull @Override - public WindowSpecExpression visitOverClause(@Nonnull RelationalParser.OverClauseContext ctx) { + public WindowSpecExpression visitOverClause(RelationalParser.OverClauseContext ctx) { return expressionVisitor.visitOverClause(ctx); } - @Nonnull @Override public Expressions visitPartitionClause(final RelationalParser.PartitionClauseContext ctx) { return expressionVisitor.visitPartitionClause(ctx); } - @Nonnull @Override - public Object visitWindowName(@Nonnull RelationalParser.WindowNameContext ctx) { + public Object visitWindowName(RelationalParser.WindowNameContext ctx) { return visitChildren(ctx); } - @Nonnull @Override public Expressions visitWindowOptionsClause(final RelationalParser.WindowOptionsClauseContext ctx) { return expressionVisitor.visitWindowOptionsClause(ctx); } - @Nonnull @Override public Expression visitWindowOption(final RelationalParser.WindowOptionContext ctx) { return expressionVisitor.visitWindowOption(ctx); } - @Nonnull @Override - public Object visitScalarFunctionName(@Nonnull RelationalParser.ScalarFunctionNameContext ctx) { + public Object visitScalarFunctionName(RelationalParser.ScalarFunctionNameContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Expressions visitFunctionArgs(@Nonnull RelationalParser.FunctionArgsContext ctx) { + public Expressions visitFunctionArgs(RelationalParser.FunctionArgsContext ctx) { return expressionVisitor.visitFunctionArgs(ctx); } - @Nonnull @Override - public Object visitFunctionArg(@Nonnull RelationalParser.FunctionArgContext ctx) { + public Object visitFunctionArg(RelationalParser.FunctionArgContext ctx) { return visitChildren(ctx); } @@ -1586,191 +1368,160 @@ public Expression visitNamedFunctionArg(final RelationalParser.NamedFunctionArgC return expressionVisitor.visitNamedFunctionArg(ctx); } - @Nonnull @Override - public Expression visitNotExpression(@Nonnull RelationalParser.NotExpressionContext ctx) { + public Expression visitNotExpression(RelationalParser.NotExpressionContext ctx) { return expressionVisitor.visitNotExpression(ctx); } - @Nonnull @Override - public Expression visitLogicalExpression(@Nonnull RelationalParser.LogicalExpressionContext ctx) { + public Expression visitLogicalExpression(RelationalParser.LogicalExpressionContext ctx) { return expressionVisitor.visitLogicalExpression(ctx); } - @Nonnull @Override - public Expression visitPredicatedExpression(@Nonnull RelationalParser.PredicatedExpressionContext ctx) { + public Expression visitPredicatedExpression(RelationalParser.PredicatedExpressionContext ctx) { return expressionVisitor.visitPredicatedExpression(ctx); } - @Nonnull @Override - public Expression visitBinaryComparisonPredicate(@Nonnull RelationalParser.BinaryComparisonPredicateContext ctx) { + public Expression visitBinaryComparisonPredicate(RelationalParser.BinaryComparisonPredicateContext ctx) { return expressionVisitor.visitBinaryComparisonPredicate(ctx); } @Override - public Expression visitSubscriptExpression(@Nonnull RelationalParser.SubscriptExpressionContext ctx) { + public Expression visitSubscriptExpression(RelationalParser.SubscriptExpressionContext ctx) { return expressionVisitor.visitSubscriptExpression(ctx); } - @Nonnull @Override - public Expression visitInList(@Nonnull RelationalParser.InListContext ctx) { + public Expression visitInList(RelationalParser.InListContext ctx) { return expressionVisitor.visitInList(ctx); } - @Nonnull @Override - public Object visitConstantExpressionAtom(@Nonnull RelationalParser.ConstantExpressionAtomContext ctx) { + public Object visitConstantExpressionAtom(RelationalParser.ConstantExpressionAtomContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Expression visitFunctionCallExpressionAtom(@Nonnull RelationalParser.FunctionCallExpressionAtomContext ctx) { + public Expression visitFunctionCallExpressionAtom(RelationalParser.FunctionCallExpressionAtomContext ctx) { return expressionVisitor.visitFunctionCallExpressionAtom(ctx); } - @Nonnull @Override - public Object visitFullColumnNameExpressionAtom(@Nonnull RelationalParser.FullColumnNameExpressionAtomContext ctx) { + public Object visitFullColumnNameExpressionAtom(RelationalParser.FullColumnNameExpressionAtomContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Expression visitBitExpressionAtom(@Nonnull RelationalParser.BitExpressionAtomContext ctx) { + public Expression visitBitExpressionAtom(RelationalParser.BitExpressionAtomContext ctx) { return expressionVisitor.visitBitExpressionAtom(ctx); } - @Nonnull @Override - public Expression visitPreparedStatementParameterAtom(@Nonnull RelationalParser.PreparedStatementParameterAtomContext ctx) { + public Expression visitPreparedStatementParameterAtom(RelationalParser.PreparedStatementParameterAtomContext ctx) { return expressionVisitor.visitPreparedStatementParameterAtom(ctx); } - @Nonnull @Override - public Object visitRecordConstructorExpressionAtom(@Nonnull RelationalParser.RecordConstructorExpressionAtomContext ctx) { + public Object visitRecordConstructorExpressionAtom(RelationalParser.RecordConstructorExpressionAtomContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitArrayConstructorExpressionAtom(@Nonnull RelationalParser.ArrayConstructorExpressionAtomContext ctx) { + public Object visitArrayConstructorExpressionAtom(RelationalParser.ArrayConstructorExpressionAtomContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Expression visitMathExpressionAtom(@Nonnull RelationalParser.MathExpressionAtomContext ctx) { + public Expression visitMathExpressionAtom(RelationalParser.MathExpressionAtomContext ctx) { return expressionVisitor.visitMathExpressionAtom(ctx); } - @Nonnull @Override - public Expression visitExistsExpressionAtom(@Nonnull RelationalParser.ExistsExpressionAtomContext ctx) { + public Expression visitExistsExpressionAtom(RelationalParser.ExistsExpressionAtomContext ctx) { return expressionVisitor.visitExistsExpressionAtom(ctx); } - @Nonnull @Override - public Expression visitPreparedStatementParameter(@Nonnull RelationalParser.PreparedStatementParameterContext ctx) { + public Expression visitPreparedStatementParameter(RelationalParser.PreparedStatementParameterContext ctx) { return expressionVisitor.visitPreparedStatementParameter(ctx); } - @Nonnull @Override - public Object visitUnaryOperator(@Nonnull RelationalParser.UnaryOperatorContext ctx) { + public Object visitUnaryOperator(RelationalParser.UnaryOperatorContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitComparisonOperator(@Nonnull RelationalParser.ComparisonOperatorContext ctx) { + public Object visitComparisonOperator(RelationalParser.ComparisonOperatorContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitLogicalOperator(@Nonnull RelationalParser.LogicalOperatorContext ctx) { + public Object visitLogicalOperator(RelationalParser.LogicalOperatorContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitBitOperator(@Nonnull RelationalParser.BitOperatorContext ctx) { + public Object visitBitOperator(RelationalParser.BitOperatorContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitMathOperator(@Nonnull RelationalParser.MathOperatorContext ctx) { + public Object visitMathOperator(RelationalParser.MathOperatorContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitJsonOperator(@Nonnull RelationalParser.JsonOperatorContext ctx) { + public Object visitJsonOperator(RelationalParser.JsonOperatorContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitCharsetNameBase(@Nonnull RelationalParser.CharsetNameBaseContext ctx) { + public Object visitCharsetNameBase(RelationalParser.CharsetNameBaseContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitIntervalTypeBase(@Nonnull RelationalParser.IntervalTypeBaseContext ctx) { + public Object visitIntervalTypeBase(RelationalParser.IntervalTypeBaseContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitKeywordsCanBeId(@Nonnull RelationalParser.KeywordsCanBeIdContext ctx) { + public Object visitKeywordsCanBeId(RelationalParser.KeywordsCanBeIdContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitFunctionNameBase(@Nonnull RelationalParser.FunctionNameBaseContext ctx) { + public Object visitFunctionNameBase(RelationalParser.FunctionNameBaseContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitFunctionNameKeyword(@Nonnull RelationalParser.FunctionNameKeywordContext ctx) { + public Object visitFunctionNameKeyword(RelationalParser.FunctionNameKeywordContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public Object visitExecuteContinuationStatement(@Nonnull RelationalParser.ExecuteContinuationStatementContext ctx) { + public Object visitExecuteContinuationStatement(RelationalParser.ExecuteContinuationStatementContext ctx) { return visitChildren(ctx); } - @Nonnull @Override - public QueryPlan visitCopyExportStatement(@Nonnull RelationalParser.CopyExportStatementContext ctx) { + public QueryPlan visitCopyExportStatement(RelationalParser.CopyExportStatementContext ctx) { return metadataPlanVisitor.visitCopyExportStatement(ctx); } - @Nonnull @Override - public QueryPlan visitCopyImportStatement(@Nonnull RelationalParser.CopyImportStatementContext ctx) { + public QueryPlan visitCopyImportStatement(RelationalParser.CopyImportStatementContext ctx) { return metadataPlanVisitor.visitCopyImportStatement(ctx); } - @Nonnull public DdlQueryFactory getDdlQueryFactory() { return ddlQueryFactory; } - @Nonnull public URI getDbUri() { return dbUri; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/DdlVisitor.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/DdlVisitor.java index c22c94ec66e..0afcc739815 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/DdlVisitor.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/DdlVisitor.java @@ -63,9 +63,7 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import org.antlr.v4.runtime.ParserRuleContext; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.net.URI; import java.util.ArrayList; import java.util.HashSet; @@ -78,6 +76,11 @@ import java.util.function.Function; import java.util.stream.Collectors; +import static com.apple.foundationdb.relational.generated.RelationalParser.IndexOptionsContext; +import static com.apple.foundationdb.relational.generated.RelationalParser.PrimitiveTypeContext; +import static com.apple.foundationdb.relational.generated.RelationalParser.UidContext; +import static com.apple.foundationdb.relational.generated.RelationalParser.VectorIndexOptionsContext; + @API(API.Status.EXPERIMENTAL) public final class DdlVisitor extends DelegatingVisitor { // The vector engines an option may apply to. HNSW is the engine used when the VECTOR_ENGINE option is absent. @@ -142,7 +145,6 @@ public final class DdlVisitor extends DelegatingVisitor { GUARDIANN_ONLY, DdlVisitor::parseOptionInt)) .build(); - @Nonnull private final RecordLayerSchemaTemplate.Builder metadataBuilder; /* @@ -152,31 +154,27 @@ public final class DdlVisitor extends DelegatingVisitor { */ private boolean containsNullableArray; - @Nonnull private final MetadataOperationsFactory metadataOperationsFactory; - @Nonnull private final URI dbUri; - private DdlVisitor(@Nonnull BaseVisitor delegate, - @Nonnull MetadataOperationsFactory metadataOperationsFactory, - @Nonnull URI dbUri) { + private DdlVisitor(BaseVisitor delegate, + MetadataOperationsFactory metadataOperationsFactory, + URI dbUri) { super(delegate); this.metadataBuilder = RecordLayerSchemaTemplate.newBuilder(); this.metadataOperationsFactory = metadataOperationsFactory; this.dbUri = dbUri; } - @Nonnull - public static DdlVisitor of(@Nonnull BaseVisitor delegate, - @Nonnull MetadataOperationsFactory metadataOperationsFactory, - @Nonnull URI dbUri) { + public static DdlVisitor of(BaseVisitor delegate, + MetadataOperationsFactory metadataOperationsFactory, + URI dbUri) { return new DdlVisitor(delegate, metadataOperationsFactory, dbUri); } - @Nonnull @Override - public DataType visitFunctionColumnType(@Nonnull final RelationalParser.FunctionColumnTypeContext ctx) { + public DataType visitFunctionColumnType(final RelationalParser.FunctionColumnTypeContext ctx) { return lookupType(ctx.customType, ctx.primitiveType(), true, ctx.ARRAY() != null); } @@ -201,9 +199,8 @@ public DataType visitFunctionColumnType(@Nonnull final RelationalParser.Function * @param ctx the parse tree. * @return a {@link RecordLayerColumn} object that captures all the properties of the column as defined by the user. */ - @Nonnull @Override - public RecordLayerColumn visitColumnDefinition(@Nonnull RelationalParser.ColumnDefinitionContext ctx) { + public RecordLayerColumn visitColumnDefinition(RelationalParser.ColumnDefinitionContext ctx) { final Identifier columnId = visitUid(ctx.colName); final boolean isArray = ctx.ARRAY() != null; final boolean isNullable @@ -224,9 +221,8 @@ public RecordLayerColumn visitColumnDefinition(@Nonnull RelationalParser.ColumnD return RecordLayerColumn.newBuilder().setName(columnId.getName()).setDataType(columnType).build(); } - @Nonnull @Override - public RecordLayerTable visitTableDefinition(@Nonnull RelationalParser.TableDefinitionContext ctx) { + public RecordLayerTable visitTableDefinition(RelationalParser.TableDefinitionContext ctx) { final var tableId = visitUid(ctx.uid()); final var columns = ctx.columnDefinition().stream().map(this::visitColumnDefinition).collect(ImmutableList.toImmutableList()); final var tableBuilder = RecordLayerTable.newBuilder(metadataBuilder.isIntermingleTables()) @@ -241,9 +237,8 @@ public RecordLayerTable visitTableDefinition(@Nonnull RelationalParser.TableDefi return tableBuilder.build(); } - @Nonnull @Override - public RecordLayerTable visitStructDefinition(@Nonnull RelationalParser.StructDefinitionContext ctx) { + public RecordLayerTable visitStructDefinition(RelationalParser.StructDefinitionContext ctx) { final var structId = visitUid(ctx.uid()); final var columns = ctx.columnDefinition().stream().map(this::visitColumnDefinition).collect(ImmutableList.toImmutableList()); final var structBuilder = RecordLayerTable.newBuilder(metadataBuilder.isIntermingleTables()) @@ -252,9 +247,8 @@ public RecordLayerTable visitStructDefinition(@Nonnull RelationalParser.StructDe return structBuilder.build(); } - @Nonnull @Override - public RecordLayerIndex visitIndexAsSelectDefinition(@Nonnull RelationalParser.IndexAsSelectDefinitionContext indexDefinitionContext) { + public RecordLayerIndex visitIndexAsSelectDefinition(RelationalParser.IndexAsSelectDefinitionContext indexDefinitionContext) { final var indexId = visitUid(indexDefinitionContext.indexName); final var ddlCatalog = metadataBuilder.build(); @@ -270,9 +264,8 @@ public RecordLayerIndex visitIndexAsSelectDefinition(@Nonnull RelationalParser.I return generator.generate(metadataBuilder, indexId.getName(), isUnique, containsNullableArray, false).build(); } - @Nonnull @Override - public RecordLayerIndex visitIndexOnSourceDefinition(@Nonnull final RelationalParser.IndexOnSourceDefinitionContext indexDefinitionContext) { + public RecordLayerIndex visitIndexOnSourceDefinition(final RelationalParser.IndexOnSourceDefinitionContext indexDefinitionContext) { final var ddlCatalog = metadataBuilder.build(); getDelegate().replaceSchemaTemplate(ddlCatalog); getDelegate().pushPlanFragment(); @@ -282,7 +275,7 @@ public RecordLayerIndex visitIndexOnSourceDefinition(@Nonnull final RelationalPa final Identifier indexId = visitUid(indexDefinitionContext.indexName); final var isUnique = indexDefinitionContext.UNIQUE() != null; - @Nullable final var indexOptions = indexDefinitionContext.indexOptions(); + @Nullable final IndexOptionsContext indexOptions = indexDefinitionContext.indexOptions(); final var useLegacyExtremum = indexOptions != null && indexOptions.indexOption().stream() .anyMatch(option -> option.LEGACY_EXTREMUM_EVER() != null); final var indexGeneratorBuilder = OnSourceIndexGenerator.newBuilder() @@ -309,7 +302,6 @@ public RecordLayerIndex visitIndexOnSourceDefinition(@Nonnull final RelationalPa return indexGeneratorBuilder.build().generate().build(); } - @Nonnull @Override public RecordLayerIndex visitVectorIndexDefinition(final RelationalParser.VectorIndexDefinitionContext indexDefinitionContext) { final var ddlCatalog = metadataBuilder.build(); @@ -360,8 +352,7 @@ public RecordLayerIndex visitVectorIndexDefinition(final RelationalParser.Vector return indexGeneratorBuilder.build().generate().setIndexType(IndexTypes.VECTOR).build(); } - @Nonnull - private LogicalOperator generateSourceAccessForIndex(@Nonnull final Identifier sourceIdentifier) { + private LogicalOperator generateSourceAccessForIndex(final Identifier sourceIdentifier) { final var semanticAnalyzer = getDelegate().getSemanticAnalyzer(); var logicalOperator = getDelegate().getPlanGenerationContext().withDisabledLiteralProcessing(() -> LogicalOperator.generateAccess(sourceIdentifier, Optional.empty(), Optional.empty(), Set.of(), @@ -389,35 +380,33 @@ semanticAnalyzer, getDelegate().getCurrentPlanFragment(), * * @param the option's value type */ - private record VectorSqlOption(@Nonnull VectorOptionKey key, - @Nonnull Set engines, - @Nonnull Function coerce) { - void writeTo(@Nonnull final BiConsumer sink, - @Nonnull final RelationalParser.VectorIndexOptionValueContext value) { + private record VectorSqlOption(VectorOptionKey key, + Set engines, + Function coerce) { + void writeTo(final BiConsumer sink, + final RelationalParser.VectorIndexOptionValueContext value) { key.put(sink, coerce.apply(value)); } } - @Nonnull - private static VectorIndexEngineKind parseVectorEngine(@Nonnull final RelationalParser.VectorEngineContext engineContext) { + private static VectorIndexEngineKind parseVectorEngine(final RelationalParser.VectorEngineContext engineContext) { return engineContext.GUARDIANN() != null ? VectorIndexEngineKind.GUARDIANN : VectorIndexEngineKind.HNSW; } - private static int parseOptionInt(@Nonnull final RelationalParser.VectorIndexOptionValueContext value) { + private static int parseOptionInt(final RelationalParser.VectorIndexOptionValueContext value) { return Integer.parseInt(value.getText()); } - private static double parseOptionDouble(@Nonnull final RelationalParser.VectorIndexOptionValueContext value) { + private static double parseOptionDouble(final RelationalParser.VectorIndexOptionValueContext value) { return Double.parseDouble(value.getText()); } - private static boolean parseOptionBoolean(@Nonnull final RelationalParser.VectorIndexOptionValueContext value) { + private static boolean parseOptionBoolean(final RelationalParser.VectorIndexOptionValueContext value) { return Boolean.parseBoolean(value.getText()); } - @Nonnull - private Map parseVectorOptions(@Nonnull final VectorIndexEngineKind engine, - @Nullable final RelationalParser.VectorIndexOptionsContext indexOptionsContext) { + private Map parseVectorOptions(final VectorIndexEngineKind engine, + @Nullable final VectorIndexOptionsContext indexOptionsContext) { final var indexOptionsBuilder = ImmutableMap.builder(); // Guardiann must be recorded explicitly; HNSW is the default when the engine option is absent, so leave it // implicit (keeps HNSW index metadata unchanged and readable by nodes that predate the engine option). @@ -457,8 +446,7 @@ private Map parseVectorOptions(@Nonnull final VectorIndexEngineK * @param metricContext the parsed metric clause * @return the corresponding metric */ - @Nonnull - private static Metric parseMetric(@Nonnull final RelationalParser.HnswMetricContext metricContext) { + private static Metric parseMetric(final RelationalParser.HnswMetricContext metricContext) { if (metricContext.DOT_PRODUCT_METRIC() != null) { return Metric.DOT_PRODUCT_METRIC; } else if (metricContext.EUCLIDEAN_METRIC() != null) { @@ -471,9 +459,8 @@ private static Metric parseMetric(@Nonnull final RelationalParser.HnswMetricCont throw Assert.failUnchecked("metric " + metricContext.getText() + " is not currently supported"); } - @Nonnull @Override - public DataType.Named visitEnumDefinition(@Nonnull RelationalParser.EnumDefinitionContext ctx) { + public DataType.Named visitEnumDefinition(RelationalParser.EnumDefinitionContext ctx) { final var enumId = visitUid(ctx.uid()); // (yhatem) we have control over the ENUM values' numbers. @@ -484,9 +471,8 @@ public DataType.Named visitEnumDefinition(@Nonnull RelationalParser.EnumDefiniti return DataType.EnumType.from(enumId.getName(), enumValues, false); } - @Nonnull @Override - public ProceduralPlan visitCreateSchemaTemplateStatement(@Nonnull RelationalParser.CreateSchemaTemplateStatementContext ctx) { + public ProceduralPlan visitCreateSchemaTemplateStatement(RelationalParser.CreateSchemaTemplateStatementContext ctx) { final var schemaTemplateId = visitUid(ctx.schemaTemplateId().uid()); // schema template version will be set automatically at update operation to lastVersion + 1 metadataBuilder.setName(schemaTemplateId.getName()).setVersion(1); @@ -560,9 +546,8 @@ public ProceduralPlan visitCreateSchemaTemplateStatement(@Nonnull RelationalPars return ProceduralPlan.of(metadataOperationsFactory.getSaveSchemaTemplateConstantAction(metadataBuilder.build(), Options.NONE)); } - @Nonnull @Override - public ProceduralPlan visitCreateSchemaStatement(@Nonnull RelationalParser.CreateSchemaStatementContext ctx) { + public ProceduralPlan visitCreateSchemaStatement(RelationalParser.CreateSchemaStatementContext ctx) { final Identifier schemaId = visitUid(ctx.schemaId().path().uid()); final var dbAndSchema = SemanticAnalyzer.parseSchemaIdentifier(schemaId); final var templateId = visitUid(ctx.schemaTemplateId().uid()); @@ -570,46 +555,41 @@ public ProceduralPlan visitCreateSchemaStatement(@Nonnull RelationalParser.Creat dbAndSchema.getRight(), templateId.getName(), Options.NONE)); } - @Nonnull @Override - public ProceduralPlan visitCreateDatabaseStatement(@Nonnull RelationalParser.CreateDatabaseStatementContext ctx) { + public ProceduralPlan visitCreateDatabaseStatement(RelationalParser.CreateDatabaseStatementContext ctx) { final var databaseId = visitUid(ctx.path().uid()); SemanticAnalyzer.validateDatabaseUri(databaseId); return ProceduralPlan.of(metadataOperationsFactory.getCreateDatabaseConstantAction(URI.create(databaseId.getName()), Options.NONE)); } - @Nonnull @Override - public ProceduralPlan visitDropDatabaseStatement(@Nonnull RelationalParser.DropDatabaseStatementContext ctx) { + public ProceduralPlan visitDropDatabaseStatement(RelationalParser.DropDatabaseStatementContext ctx) { final var databaseId = visitUid(ctx.path().uid()); SemanticAnalyzer.validateDatabaseUri(databaseId); boolean throwIfDoesNotExist = ctx.ifExists() == null; return ProceduralPlan.of(metadataOperationsFactory.getDropDatabaseConstantAction(URI.create(databaseId.getName()), throwIfDoesNotExist, Options.NONE)); } - @Nonnull @Override - public ProceduralPlan visitDropSchemaStatement(@Nonnull RelationalParser.DropSchemaStatementContext ctx) { + public ProceduralPlan visitDropSchemaStatement(RelationalParser.DropSchemaStatementContext ctx) { final var schemaId = visitUid(ctx.uid()); final var dbAndSchema = SemanticAnalyzer.parseSchemaIdentifier(schemaId); Assert.thatUnchecked(dbAndSchema.getLeft().isPresent(), ErrorCode.UNKNOWN_DATABASE, () -> String.format(Locale.ROOT, "invalid database identifier in '%s'", ctx.uid().getText())); return ProceduralPlan.of(metadataOperationsFactory.getDropSchemaConstantAction(dbAndSchema.getLeft().get(), dbAndSchema.getRight(), Options.NONE)); } - @Nonnull @Override - public ProceduralPlan visitDropSchemaTemplateStatement(@Nonnull RelationalParser.DropSchemaTemplateStatementContext ctx) { + public ProceduralPlan visitDropSchemaTemplateStatement(RelationalParser.DropSchemaTemplateStatementContext ctx) { final var schemaTemplateId = visitUid(ctx.uid()); boolean throwIfDoesNotExist = ctx.ifExists() == null; return ProceduralPlan.of(metadataOperationsFactory.getDropSchemaTemplateConstantAction(schemaTemplateId.getName(), throwIfDoesNotExist, Options.NONE)); } - @Nonnull - private RecordLayerInvokedRoutine getInvokedRoutineMetadata(@Nonnull final ParserRuleContext functionCtx, - @Nonnull final RelationalParser.FunctionSpecificationContext functionSpecCtx, - @Nonnull final RelationalParser.RoutineBodyContext bodyCtx, - @Nonnull final RecordLayerSchemaTemplate ddlCatalog) { + private RecordLayerInvokedRoutine getInvokedRoutineMetadata(final ParserRuleContext functionCtx, + final RelationalParser.FunctionSpecificationContext functionSpecCtx, + final RelationalParser.RoutineBodyContext bodyCtx, + final RecordLayerSchemaTemplate ddlCatalog) { // parse the index SQL query using the newly constructed metadata. getDelegate().replaceSchemaTemplate(ddlCatalog); @@ -655,9 +635,8 @@ private RecordLayerInvokedRoutine getInvokedRoutineMetadata(@Nonnull final Parse } } - @Nonnull - private RecordLayerView getViewMetadata(@Nonnull final RelationalParser.ViewDefinitionContext viewCtx, - @Nonnull final RecordLayerSchemaTemplate ddlCatalog) { + private RecordLayerView getViewMetadata(final RelationalParser.ViewDefinitionContext viewCtx, + final RecordLayerSchemaTemplate ddlCatalog) { // parse the view SQL query using the newly constructed metadata. getDelegate().replaceSchemaTemplate(ddlCatalog); @@ -690,7 +669,7 @@ private RecordLayerView getViewMetadata(@Nonnull final RelationalParser.ViewDefi } @Override - public ProceduralPlan visitCreateTempFunction(@Nonnull RelationalParser.CreateTempFunctionContext ctx) { + public ProceduralPlan visitCreateTempFunction(RelationalParser.CreateTempFunctionContext ctx) { final var invokedRoutine = getInvokedRoutineMetadata(ctx, ctx.tempSqlInvokedFunction().functionSpecification(), ctx.tempSqlInvokedFunction().routineBody(), getDelegate().getSchemaTemplate()); var throwIfExists = ctx.REPLACE() == null; @@ -699,24 +678,24 @@ public ProceduralPlan visitCreateTempFunction(@Nonnull RelationalParser.CreateTe } @Override - public ProceduralPlan visitDropTempFunction(@Nonnull RelationalParser.DropTempFunctionContext ctx) { + public ProceduralPlan visitDropTempFunction(RelationalParser.DropTempFunctionContext ctx) { final var functionName = visitFullId(ctx.schemaQualifiedRoutineName).toString(); var throwIfNotExists = ctx.IF() == null && ctx.EXISTS() == null; return ProceduralPlan.of(metadataOperationsFactory.getDropTemporaryFunctionConstantAction(throwIfNotExists, functionName)); } @Override - public CompiledSqlFunction visitTempSqlInvokedFunction(@Nonnull RelationalParser.TempSqlInvokedFunctionContext ctx) { + public CompiledSqlFunction visitTempSqlInvokedFunction(RelationalParser.TempSqlInvokedFunctionContext ctx) { return (CompiledSqlFunction)visitSqlInvokedFunction(ctx.functionSpecification(), ctx.routineBody(), true); } @Override - public UserDefinedFunction visitSqlInvokedFunction(@Nonnull RelationalParser.SqlInvokedFunctionContext ctx) { + public UserDefinedFunction visitSqlInvokedFunction(RelationalParser.SqlInvokedFunctionContext ctx) { return visitSqlInvokedFunction(ctx.functionSpecification(), ctx.routineBody(), false); } - private UserDefinedFunction visitSqlInvokedFunction(@Nonnull final RelationalParser.FunctionSpecificationContext functionSpecCtx, - @Nonnull final RelationalParser.RoutineBodyContext bodyCtx, + private UserDefinedFunction visitSqlInvokedFunction(final RelationalParser.FunctionSpecificationContext functionSpecCtx, + final RelationalParser.RoutineBodyContext bodyCtx, boolean isTemporary) { // run implementation-specific validations. final var props = functionSpecCtx.routineCharacteristics(); @@ -799,9 +778,8 @@ private UserDefinedFunction visitSqlInvokedFunction(@Nonnull final RelationalPar return finalStepBuilder.build(); } - @Nonnull @Override - public Expression visitUserDefinedMacroFunctionStatementBody(@Nonnull final RelationalParser.UserDefinedMacroFunctionStatementBodyContext ctx) { + public Expression visitUserDefinedMacroFunctionStatementBody(final RelationalParser.UserDefinedMacroFunctionStatementBodyContext ctx) { return Assert.castUnchecked(visit(ctx.expression()), Expression.class); } @@ -811,7 +789,7 @@ public LogicalOperator visitStatementBody(final RelationalParser.StatementBodyCo } @Override - public Expressions visitSqlParameterDeclarationList(@Nonnull RelationalParser.SqlParameterDeclarationListContext ctx) { + public Expressions visitSqlParameterDeclarationList(RelationalParser.SqlParameterDeclarationListContext ctx) { if (ctx.sqlParameterDeclarations() == null) { return Expressions.empty(); } @@ -833,7 +811,7 @@ public Expressions visitSqlParameterDeclarations(final RelationalParser.SqlParam } @Override - public Expression visitSqlParameterDeclaration(@Nonnull RelationalParser.SqlParameterDeclarationContext ctx) { + public Expression visitSqlParameterDeclaration(RelationalParser.SqlParameterDeclarationContext ctx) { Assert.thatUnchecked(ctx.sqlParameterName != null, "unnamed parameters not supported"); final var parameterName = visitUid(ctx.sqlParameterName); final var parameterType = visitFunctionColumnType(ctx.parameterType); @@ -850,15 +828,14 @@ public Expression visitSqlParameterDeclaration(@Nonnull RelationalParser.SqlPara } @Override - public DataType visitReturnsType(@Nonnull RelationalParser.ReturnsTypeContext ctx) { + public DataType visitReturnsType(RelationalParser.ReturnsTypeContext ctx) { Assert.isNullUnchecked(ctx.returnsTableType(), ErrorCode.UNSUPPORTED_OPERATION, "table return type is not supported"); return lookupType(ctx.columnType().customType, ctx.columnType().primitiveType(), true, ctx.ARRAY() != null); } - @Nonnull - private DataType lookupType(@Nullable RelationalParser.UidContext customType, - @Nullable RelationalParser.PrimitiveTypeContext primitiveTypeContext, + private DataType lookupType(@Nullable UidContext customType, + @Nullable PrimitiveTypeContext primitiveTypeContext, boolean isNullable, boolean isRepeated) { final SemanticAnalyzer.ParsedTypeInfo typeInfo; @@ -875,9 +852,8 @@ private DataType lookupType(@Nullable RelationalParser.UidContext customType, } // TODO: remove - @Nonnull @Override - public Boolean visitNullColumnConstraint(@Nonnull RelationalParser.NullColumnConstraintContext ctx) { + public Boolean visitNullColumnConstraint(RelationalParser.NullColumnConstraintContext ctx) { return ctx.nullNotnull().NOT() == null; } @@ -905,17 +881,15 @@ public Boolean visitNullColumnConstraint(@Nonnull RelationalParser.NullColumnCon * issue #4323 * for the underlying case-sensitivity behavior of the normalizer.

*/ - @Nonnull - private static String rewriteDeclaredFunctionToStandalone(@Nonnull final RelationalParser.DeclaredFunctionContext ctx, - @Nonnull final String sourceText) { + private static String rewriteDeclaredFunctionToStandalone(final RelationalParser.DeclaredFunctionContext ctx, + final String sourceText) { final String name = sliceSource(sourceText, ctx.functionName); final String paramList = sliceSource(sourceText, ctx.sqlParameterDeclarationList()); final String body = sliceSource(sourceText, ctx.functionBody); return "CREATE TEMPORARY FUNCTION " + name + paramList + " ON COMMIT DROP FUNCTION AS " + body; } - @Nonnull - private static String sliceSource(@Nonnull final String sourceText, @Nonnull final ParserRuleContext ctx) { + private static String sliceSource(final String sourceText, final ParserRuleContext ctx) { return sourceText.substring(ctx.start.getStartIndex(), ctx.stop.getStopIndex() + 1); } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/DelegatingVisitor.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/DelegatingVisitor.java index e5c3e2ba35e..125130fd0d0 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/DelegatingVisitor.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/DelegatingVisitor.java @@ -42,172 +42,144 @@ import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.RuleNode; import org.antlr.v4.runtime.tree.TerminalNode; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.List; import java.util.Set; @API(API.Status.EXPERIMENTAL) public class DelegatingVisitor implements TypedVisitor { - @Nonnull private final D delegate; - public DelegatingVisitor(@Nonnull D delegate) { + public DelegatingVisitor(D delegate) { this.delegate = delegate; } - @Nonnull public D getDelegate() { return delegate; } - @Nonnull @Override - public Object visitRoot(@Nonnull RelationalParser.RootContext ctx) { + public Object visitRoot(RelationalParser.RootContext ctx) { return getDelegate().visitRoot(ctx); } - @Nonnull @Override - public Object visitStatements(@Nonnull RelationalParser.StatementsContext ctx) { + public Object visitStatements(RelationalParser.StatementsContext ctx) { return getDelegate().visitStatements(ctx); } @Nullable @Override - public Object visitStatement(@Nonnull RelationalParser.StatementContext ctx) { + public Object visitStatement(RelationalParser.StatementContext ctx) { return getDelegate().visitStatement(ctx); } - @Nonnull @Override - public QueryPlan.LogicalQueryPlan visitDmlStatement(@Nonnull RelationalParser.DmlStatementContext ctx) { + public QueryPlan.LogicalQueryPlan visitDmlStatement(RelationalParser.DmlStatementContext ctx) { return getDelegate().visitDmlStatement(ctx); } - @Nonnull @Override public Object visitDdlStatement(RelationalParser.DdlStatementContext ctx) { return getDelegate().visitDdlStatement(ctx); } - @Nonnull @Override - public Object visitTransactionStatement(@Nonnull RelationalParser.TransactionStatementContext ctx) { + public Object visitTransactionStatement(RelationalParser.TransactionStatementContext ctx) { return getDelegate().visitTransactionStatement(ctx); } - @Nonnull @Override - public Object visitPreparedStatement(@Nonnull RelationalParser.PreparedStatementContext ctx) { + public Object visitPreparedStatement(RelationalParser.PreparedStatementContext ctx) { return getDelegate().visitPreparedStatement(ctx); } - @Nonnull @Override - public Object visitAdministrationStatement(@Nonnull RelationalParser.AdministrationStatementContext ctx) { + public Object visitAdministrationStatement(RelationalParser.AdministrationStatementContext ctx) { return getDelegate().visitAdministrationStatement(ctx); } - @Nonnull @Override - public Object visitUtilityStatement(@Nonnull RelationalParser.UtilityStatementContext ctx) { + public Object visitUtilityStatement(RelationalParser.UtilityStatementContext ctx) { return getDelegate().visitUtilityStatement(ctx); } - @Nonnull @Override - public Object visitTemplateClause(@Nonnull RelationalParser.TemplateClauseContext ctx) { + public Object visitTemplateClause(RelationalParser.TemplateClauseContext ctx) { return getDelegate().visitTemplateClause(ctx); } - @Nonnull @Override - public ProceduralPlan visitCreateSchemaStatement(@Nonnull RelationalParser.CreateSchemaStatementContext ctx) { + public ProceduralPlan visitCreateSchemaStatement(RelationalParser.CreateSchemaStatementContext ctx) { return getDelegate().visitCreateSchemaStatement(ctx); } - @Nonnull @Override - public ProceduralPlan visitCreateSchemaTemplateStatement(@Nonnull RelationalParser.CreateSchemaTemplateStatementContext ctx) { + public ProceduralPlan visitCreateSchemaTemplateStatement(RelationalParser.CreateSchemaTemplateStatementContext ctx) { return getDelegate().visitCreateSchemaTemplateStatement(ctx); } - @Nonnull @Override - public ProceduralPlan visitCreateDatabaseStatement(@Nonnull RelationalParser.CreateDatabaseStatementContext ctx) { + public ProceduralPlan visitCreateDatabaseStatement(RelationalParser.CreateDatabaseStatementContext ctx) { return getDelegate().visitCreateDatabaseStatement(ctx); } - @Nonnull @Override - public Object visitOptionsClause(@Nonnull RelationalParser.OptionsClauseContext ctx) { + public Object visitOptionsClause(RelationalParser.OptionsClauseContext ctx) { return getDelegate().visitOptionsClause(ctx); } - @Nonnull @Override - public Object visitOption(@Nonnull RelationalParser.OptionContext ctx) { + public Object visitOption(RelationalParser.OptionContext ctx) { return getDelegate().visitOption(ctx); } - @Nonnull @Override - public ProceduralPlan visitDropDatabaseStatement(@Nonnull RelationalParser.DropDatabaseStatementContext ctx) { + public ProceduralPlan visitDropDatabaseStatement(RelationalParser.DropDatabaseStatementContext ctx) { return getDelegate().visitDropDatabaseStatement(ctx); } - @Nonnull @Override - public ProceduralPlan visitDropSchemaTemplateStatement(@Nonnull RelationalParser.DropSchemaTemplateStatementContext ctx) { + public ProceduralPlan visitDropSchemaTemplateStatement(RelationalParser.DropSchemaTemplateStatementContext ctx) { return getDelegate().visitDropSchemaTemplateStatement(ctx); } - @Nonnull @Override - public ProceduralPlan visitDropSchemaStatement(@Nonnull RelationalParser.DropSchemaStatementContext ctx) { + public ProceduralPlan visitDropSchemaStatement(RelationalParser.DropSchemaStatementContext ctx) { return getDelegate().visitDropSchemaStatement(ctx); } - @Nonnull @Override - public RecordLayerTable visitStructDefinition(@Nonnull RelationalParser.StructDefinitionContext ctx) { + public RecordLayerTable visitStructDefinition(RelationalParser.StructDefinitionContext ctx) { return getDelegate().visitStructDefinition(ctx); } - @Nonnull @Override - public RecordLayerTable visitTableDefinition(@Nonnull RelationalParser.TableDefinitionContext ctx) { + public RecordLayerTable visitTableDefinition(RelationalParser.TableDefinitionContext ctx) { return getDelegate().visitTableDefinition(ctx); } - @Nonnull @Override - public Object visitColumnDefinition(@Nonnull RelationalParser.ColumnDefinitionContext ctx) { + public Object visitColumnDefinition(RelationalParser.ColumnDefinitionContext ctx) { return getDelegate().visitColumnDefinition(ctx); } - @Nonnull @Override - public DataType visitFunctionColumnType(@Nonnull final RelationalParser.FunctionColumnTypeContext ctx) { + public DataType visitFunctionColumnType(final RelationalParser.FunctionColumnTypeContext ctx) { return getDelegate().visitFunctionColumnType(ctx); } - @Nonnull @Override - public Object visitColumnType(@Nonnull RelationalParser.ColumnTypeContext ctx) { + public Object visitColumnType(RelationalParser.ColumnTypeContext ctx) { return getDelegate().visitColumnType(ctx); } - @Nonnull @Override - public Object visitPrimitiveType(@Nonnull RelationalParser.PrimitiveTypeContext ctx) { + public Object visitPrimitiveType(RelationalParser.PrimitiveTypeContext ctx) { return getDelegate().visitPrimitiveType(ctx); } - @Nonnull @Override public Object visitVectorType(final RelationalParser.VectorTypeContext ctx) { return getDelegate().visitVectorType(ctx); @@ -218,27 +190,23 @@ public Object visitVectorElementType(final RelationalParser.VectorElementTypeCon return getDelegate().visitVectorElementType(ctx); } - @Nonnull @Override - public Boolean visitNullColumnConstraint(@Nonnull RelationalParser.NullColumnConstraintContext ctx) { + public Boolean visitNullColumnConstraint(RelationalParser.NullColumnConstraintContext ctx) { return getDelegate().visitNullColumnConstraint(ctx); } - @Nonnull @Override - public Object visitPrimaryKeyDefinition(@Nonnull RelationalParser.PrimaryKeyDefinitionContext ctx) { + public Object visitPrimaryKeyDefinition(RelationalParser.PrimaryKeyDefinitionContext ctx) { return getDelegate().visitPrimaryKeyDefinition(ctx); } - @Nonnull @Override - public List visitFullIdList(@Nonnull RelationalParser.FullIdListContext ctx) { + public List visitFullIdList(RelationalParser.FullIdListContext ctx) { return getDelegate().visitFullIdList(ctx); } - @Nonnull @Override - public DataType.Named visitEnumDefinition(@Nonnull RelationalParser.EnumDefinitionContext ctx) { + public DataType.Named visitEnumDefinition(RelationalParser.EnumDefinitionContext ctx) { return getDelegate().visitEnumDefinition(ctx); } @@ -287,15 +255,13 @@ public Object visitVectorIndexOptionValue(final RelationalParser.VectorIndexOpti return getDelegate().visitVectorIndexOptionValue(ctx); } - @Nonnull @Override - public Object visitIndexAttributes(@Nonnull RelationalParser.IndexAttributesContext ctx) { + public Object visitIndexAttributes(RelationalParser.IndexAttributesContext ctx) { return getDelegate().visitIndexAttributes(ctx); } - @Nonnull @Override - public Object visitIndexAttribute(@Nonnull RelationalParser.IndexAttributeContext ctx) { + public Object visitIndexAttribute(RelationalParser.IndexAttributeContext ctx) { return getDelegate().visitIndexAttribute(ctx); } @@ -335,7 +301,7 @@ public CompiledSqlFunction visitTempSqlInvokedFunction(final RelationalParser.Te } @Override - public UserDefinedFunction visitSqlInvokedFunction(@Nonnull RelationalParser.SqlInvokedFunctionContext ctx) { + public UserDefinedFunction visitSqlInvokedFunction(RelationalParser.SqlInvokedFunctionContext ctx) { return getDelegate().visitSqlInvokedFunction(ctx); } @@ -429,63 +395,54 @@ public RecordLayerInvokedRoutine visitFunctionSpecification(final RelationalPars return getDelegate().visitFunctionSpecification(ctx); } - @Nonnull @Override - public Object visitCharSet(@Nonnull RelationalParser.CharSetContext ctx) { + public Object visitCharSet(RelationalParser.CharSetContext ctx) { return getDelegate().visitCharSet(ctx); } - @Nonnull @Override - public Object visitIntervalType(@Nonnull RelationalParser.IntervalTypeContext ctx) { + public Object visitIntervalType(RelationalParser.IntervalTypeContext ctx) { return getDelegate().visitIntervalType(ctx); } - @Nonnull @Override - public Object visitSchemaId(@Nonnull RelationalParser.SchemaIdContext ctx) { + public Object visitSchemaId(RelationalParser.SchemaIdContext ctx) { return getDelegate().visitSchemaId(ctx); } - @Nonnull @Override - public Object visitPath(@Nonnull RelationalParser.PathContext ctx) { + public Object visitPath(RelationalParser.PathContext ctx) { return getDelegate().visitPath(ctx); } - @Nonnull @Override - public Object visitSchemaTemplateId(@Nonnull RelationalParser.SchemaTemplateIdContext ctx) { + public Object visitSchemaTemplateId(RelationalParser.SchemaTemplateIdContext ctx) { return getDelegate().visitSchemaTemplateId(ctx); } - @Nonnull @Override - public LogicalOperator visitDeleteStatement(@Nonnull RelationalParser.DeleteStatementContext ctx) { + public LogicalOperator visitDeleteStatement(RelationalParser.DeleteStatementContext ctx) { return getDelegate().visitDeleteStatement(ctx); } - @Nonnull @Override - public LogicalOperator visitInsertStatement(@Nonnull RelationalParser.InsertStatementContext ctx) { + public LogicalOperator visitInsertStatement(RelationalParser.InsertStatementContext ctx) { return getDelegate().visitInsertStatement(ctx); } - @Nonnull @Override - public QueryPlan.LogicalQueryPlan visitSelectStatement(@Nonnull RelationalParser.SelectStatementContext ctx) { + public QueryPlan.LogicalQueryPlan visitSelectStatement(RelationalParser.SelectStatementContext ctx) { return getDelegate().visitSelectStatement(ctx); } - @Nonnull @Override - public LogicalOperator visitQuery(@Nonnull RelationalParser.QueryContext ctx) { + public LogicalOperator visitQuery(RelationalParser.QueryContext ctx) { return getDelegate().visitQuery(ctx); } @Nullable @Override - public Void visitCtes(@Nonnull RelationalParser.CtesContext ctx) { + public Void visitCtes(RelationalParser.CtesContext ctx) { return getDelegate().visitCtes(ctx); } @@ -494,14 +451,13 @@ public Object visitTraversalOrderClause(final RelationalParser.TraversalOrderCla return getDelegate().visitTraversalOrderClause(ctx); } - @Nonnull @Override - public LogicalOperator visitNamedQuery(@Nonnull RelationalParser.NamedQueryContext ctx) { + public LogicalOperator visitNamedQuery(RelationalParser.NamedQueryContext ctx) { return getDelegate().visitNamedQuery(ctx); } @Override - public LogicalOperator visitTableFunction(@Nonnull RelationalParser.TableFunctionContext ctx) { + public LogicalOperator visitTableFunction(RelationalParser.TableFunctionContext ctx) { return getDelegate().visitTableFunction(ctx); } @@ -511,1009 +467,850 @@ public Expressions visitNamedOrUnnamedFunctionArgs(RelationalParser.NamedOrUnnam } @Override - public Identifier visitTableFunctionName(@Nonnull RelationalParser.TableFunctionNameContext ctx) { + public Identifier visitTableFunctionName(RelationalParser.TableFunctionNameContext ctx) { return getDelegate().visitTableFunctionName(ctx); } - @Nonnull @Override - public Expression visitContinuationAtom(@Nonnull RelationalParser.ContinuationAtomContext ctx) { + public Expression visitContinuationAtom(RelationalParser.ContinuationAtomContext ctx) { return getDelegate().visitContinuationAtom(ctx); } - @Nonnull @Override - public LogicalOperator visitQueryTermDefault(@Nonnull RelationalParser.QueryTermDefaultContext ctx) { + public LogicalOperator visitQueryTermDefault(RelationalParser.QueryTermDefaultContext ctx) { return getDelegate().visitQueryTermDefault(ctx); } - @Nonnull @Override public LogicalOperator visitSetQuery(RelationalParser.SetQueryContext ctx) { return getDelegate().visitSetQuery(ctx); } - @Nonnull @Override - public LogicalOperator visitInsertStatementValueSelect(@Nonnull RelationalParser.InsertStatementValueSelectContext ctx) { + public LogicalOperator visitInsertStatementValueSelect(RelationalParser.InsertStatementValueSelectContext ctx) { return getDelegate().visitInsertStatementValueSelect(ctx); } - @Nonnull @Override - public LogicalOperator visitInsertStatementValueValues(@Nonnull RelationalParser.InsertStatementValueValuesContext ctx) { + public LogicalOperator visitInsertStatementValueValues(RelationalParser.InsertStatementValueValuesContext ctx) { return getDelegate().visitInsertStatementValueValues(ctx); } - @Nonnull @Override - public Expressions visitUpdatedElement(@Nonnull RelationalParser.UpdatedElementContext ctx) { + public Expressions visitUpdatedElement(RelationalParser.UpdatedElementContext ctx) { return getDelegate().visitUpdatedElement(ctx); } - @Nonnull @Override - public Object visitAssignmentField(@Nonnull RelationalParser.AssignmentFieldContext ctx) { + public Object visitAssignmentField(RelationalParser.AssignmentFieldContext ctx) { return getDelegate().visitAssignmentField(ctx); } - @Nonnull @Override - public LogicalOperator visitUpdateStatement(@Nonnull RelationalParser.UpdateStatementContext ctx) { + public LogicalOperator visitUpdateStatement(RelationalParser.UpdateStatementContext ctx) { return getDelegate().visitUpdateStatement(ctx); } - @Nonnull @Override - public List visitOrderByClause(@Nonnull RelationalParser.OrderByClauseContext ctx) { + public List visitOrderByClause(RelationalParser.OrderByClauseContext ctx) { return getDelegate().visitOrderByClause(ctx); } - @Nonnull @Override - public OrderByExpression visitOrderByExpression(@Nonnull RelationalParser.OrderByExpressionContext ctx) { + public OrderByExpression visitOrderByExpression(RelationalParser.OrderByExpressionContext ctx) { return getDelegate().visitOrderByExpression(ctx); } - @Nonnull @Override - public RecordLayerIndex visitIndexAsSelectDefinition(@Nonnull RelationalParser.IndexAsSelectDefinitionContext ctx) { + public RecordLayerIndex visitIndexAsSelectDefinition(RelationalParser.IndexAsSelectDefinitionContext ctx) { return getDelegate().visitIndexAsSelectDefinition(ctx); } - @Nonnull @Override - public RecordLayerIndex visitIndexOnSourceDefinition(@Nonnull RelationalParser.IndexOnSourceDefinitionContext ctx) { + public RecordLayerIndex visitIndexOnSourceDefinition(RelationalParser.IndexOnSourceDefinitionContext ctx) { return getDelegate().visitIndexOnSourceDefinition(ctx); } - @Nonnull @Override public RecordLayerIndex visitVectorIndexDefinition(final RelationalParser.VectorIndexDefinitionContext ctx) { return getDelegate().visitVectorIndexDefinition(ctx); } - @Nonnull @Override - public Object visitIndexColumnList(@Nonnull RelationalParser.IndexColumnListContext ctx) { + public Object visitIndexColumnList(RelationalParser.IndexColumnListContext ctx) { return getDelegate().visitIndexColumnList(ctx); } - @Nonnull @Override - public Object visitIndexColumnSpec(@Nonnull RelationalParser.IndexColumnSpecContext ctx) { + public Object visitIndexColumnSpec(RelationalParser.IndexColumnSpecContext ctx) { return getDelegate().visitIndexColumnSpec(ctx); } - @Nonnull @Override - public Object visitIncludeClause(@Nonnull RelationalParser.IncludeClauseContext ctx) { + public Object visitIncludeClause(RelationalParser.IncludeClauseContext ctx) { return getDelegate().visitIncludeClause(ctx); } @Override @Nullable - public Void visitTableSources(@Nonnull RelationalParser.TableSourcesContext ctx) { + public Void visitTableSources(RelationalParser.TableSourcesContext ctx) { return getDelegate().visitTableSources(ctx); } @Nullable @Override - public Void visitTableSourceBase(@Nonnull RelationalParser.TableSourceBaseContext ctx) { + public Void visitTableSourceBase(RelationalParser.TableSourceBaseContext ctx) { return getDelegate().visitTableSourceBase(ctx); } - @Nonnull @Override - public LogicalOperator visitAtomTableItem(@Nonnull RelationalParser.AtomTableItemContext ctx) { + public LogicalOperator visitAtomTableItem(RelationalParser.AtomTableItemContext ctx) { return getDelegate().visitAtomTableItem(ctx); } - @Nonnull @Override - public LogicalOperator visitSubqueryTableItem(@Nonnull RelationalParser.SubqueryTableItemContext ctx) { + public LogicalOperator visitSubqueryTableItem(RelationalParser.SubqueryTableItemContext ctx) { return getDelegate().visitSubqueryTableItem(ctx); } - @Nonnull @Override - public LogicalOperator visitInlineTableItem(@Nonnull final RelationalParser.InlineTableItemContext ctx) { + public LogicalOperator visitInlineTableItem(final RelationalParser.InlineTableItemContext ctx) { return getDelegate().visitInlineTableItem(ctx); } @Override - public LogicalOperator visitTableValuedFunction(@Nonnull final RelationalParser.TableValuedFunctionContext ctx) { + public LogicalOperator visitTableValuedFunction(final RelationalParser.TableValuedFunctionContext ctx) { return getDelegate().visitTableValuedFunction(ctx); } - @Nonnull @Override - public Set visitIndexHint(@Nonnull RelationalParser.IndexHintContext ctx) { + public Set visitIndexHint(RelationalParser.IndexHintContext ctx) { return getDelegate().visitIndexHint(ctx); } - @Nonnull @Override - public Object visitIndexHintType(@Nonnull RelationalParser.IndexHintTypeContext ctx) { + public Object visitIndexHintType(RelationalParser.IndexHintTypeContext ctx) { return getDelegate().visitIndexHintType(ctx); } - @Nonnull @Override - public NonnullPair visitInlineTableDefinition(@Nonnull RelationalParser.InlineTableDefinitionContext ctx) { + public NonnullPair visitInlineTableDefinition(RelationalParser.InlineTableDefinitionContext ctx) { return getDelegate().visitInlineTableDefinition(ctx); } @Nullable @Override - public Object visitInnerJoin(@Nonnull RelationalParser.InnerJoinContext ctx) { + public Object visitInnerJoin(RelationalParser.InnerJoinContext ctx) { return getDelegate().visitInnerJoin(ctx); } - @Nonnull @Override - public Object visitStraightJoin(@Nonnull RelationalParser.StraightJoinContext ctx) { + public Object visitStraightJoin(RelationalParser.StraightJoinContext ctx) { return getDelegate().visitStraightJoin(ctx); } @Nullable @Override - public Object visitOuterJoin(@Nonnull RelationalParser.OuterJoinContext ctx) { + public Object visitOuterJoin(RelationalParser.OuterJoinContext ctx) { return getDelegate().visitOuterJoin(ctx); } - @Nonnull @Override - public Object visitNaturalJoin(@Nonnull RelationalParser.NaturalJoinContext ctx) { + public Object visitNaturalJoin(RelationalParser.NaturalJoinContext ctx) { return getDelegate().visitNaturalJoin(ctx); } - @Nonnull @Override - public LogicalOperator visitSimpleTable(@Nonnull RelationalParser.SimpleTableContext ctx) { + public LogicalOperator visitSimpleTable(RelationalParser.SimpleTableContext ctx) { return getDelegate().visitSimpleTable(ctx); } - @Nonnull @Override public LogicalOperator visitParenthesisQuery(RelationalParser.ParenthesisQueryContext ctx) { return getDelegate().visitParenthesisQuery(ctx); } - @Nonnull @Override - public Expressions visitSelectElements(@Nonnull RelationalParser.SelectElementsContext ctx) { + public Expressions visitSelectElements(RelationalParser.SelectElementsContext ctx) { return getDelegate().visitSelectElements(ctx); } - @Nonnull @Override - public Expression visitSelectStarElement(@Nonnull RelationalParser.SelectStarElementContext ctx) { + public Expression visitSelectStarElement(RelationalParser.SelectStarElementContext ctx) { return getDelegate().visitSelectStarElement(ctx); } - @Nonnull @Override - public Object visitSelectQualifierStarElement(@Nonnull RelationalParser.SelectQualifierStarElementContext ctx) { + public Object visitSelectQualifierStarElement(RelationalParser.SelectQualifierStarElementContext ctx) { return getDelegate().visitSelectQualifierStarElement(ctx); } - @Nonnull @Override - public Expression visitSelectExpressionElement(@Nonnull RelationalParser.SelectExpressionElementContext ctx) { + public Expression visitSelectExpressionElement(RelationalParser.SelectExpressionElementContext ctx) { return getDelegate().visitSelectExpressionElement(ctx); } @Override @Nullable - public Void visitFromClause(@Nonnull RelationalParser.FromClauseContext ctx) { + public Void visitFromClause(RelationalParser.FromClauseContext ctx) { return getDelegate().visitFromClause(ctx); } - @Nonnull @Override - public Expressions visitGroupByClause(@Nonnull RelationalParser.GroupByClauseContext ctx) { + public Expressions visitGroupByClause(RelationalParser.GroupByClauseContext ctx) { return getDelegate().visitGroupByClause(ctx); } - @Nonnull @Override - public Expression visitWhereExpr(@Nonnull RelationalParser.WhereExprContext ctx) { + public Expression visitWhereExpr(RelationalParser.WhereExprContext ctx) { return getDelegate().visitWhereExpr(ctx); } - @Nonnull @Override - public Expression visitHavingClause(@Nonnull RelationalParser.HavingClauseContext ctx) { + public Expression visitHavingClause(RelationalParser.HavingClauseContext ctx) { return getDelegate().visitHavingClause(ctx); } - @Nonnull @Override public Expression visitQualifyClause(final RelationalParser.QualifyClauseContext ctx) { return getDelegate().visitQualifyClause(ctx); } - @Nonnull @Override - public Expression visitGroupByItem(@Nonnull RelationalParser.GroupByItemContext ctx) { + public Expression visitGroupByItem(RelationalParser.GroupByItemContext ctx) { return getDelegate().visitGroupByItem(ctx); } - @Nonnull @Override - public Expression visitLimitClause(@Nonnull RelationalParser.LimitClauseContext ctx) { + public Expression visitLimitClause(RelationalParser.LimitClauseContext ctx) { return getDelegate().visitLimitClause(ctx); } - @Nonnull @Override - public Expression visitLimitClauseAtom(@Nonnull RelationalParser.LimitClauseAtomContext ctx) { + public Expression visitLimitClauseAtom(RelationalParser.LimitClauseAtomContext ctx) { return getDelegate().visitLimitClauseAtom(ctx); } - @Nonnull @Override - public Object visitStatementOptions(@Nonnull RelationalParser.StatementOptionsContext ctx) { + public Object visitStatementOptions(RelationalParser.StatementOptionsContext ctx) { return getDelegate().visitStatementOptions(ctx); } - @Nonnull @Override - public Object visitStatementOption(@Nonnull RelationalParser.StatementOptionContext ctx) { + public Object visitStatementOption(RelationalParser.StatementOptionContext ctx) { return getDelegate().visitStatementOption(ctx); } - @Nonnull @Override - public Object visitStartTransaction(@Nonnull RelationalParser.StartTransactionContext ctx) { + public Object visitStartTransaction(RelationalParser.StartTransactionContext ctx) { return getDelegate().visitStartTransaction(ctx); } - @Nonnull @Override - public Object visitCommitStatement(@Nonnull RelationalParser.CommitStatementContext ctx) { + public Object visitCommitStatement(RelationalParser.CommitStatementContext ctx) { return getDelegate().visitCommitStatement(ctx); } - @Nonnull @Override - public Object visitRollbackStatement(@Nonnull RelationalParser.RollbackStatementContext ctx) { + public Object visitRollbackStatement(RelationalParser.RollbackStatementContext ctx) { return getDelegate().visitRollbackStatement(ctx); } - @Nonnull @Override - public Object visitSetAutocommitStatement(@Nonnull RelationalParser.SetAutocommitStatementContext ctx) { + public Object visitSetAutocommitStatement(RelationalParser.SetAutocommitStatementContext ctx) { return getDelegate().visitSetAutocommitStatement(ctx); } - @Nonnull @Override - public Object visitSetTransactionStatement(@Nonnull RelationalParser.SetTransactionStatementContext ctx) { + public Object visitSetTransactionStatement(RelationalParser.SetTransactionStatementContext ctx) { return getDelegate().visitSetTransactionStatement(ctx); } - @Nonnull @Override - public Object visitTransactionOption(@Nonnull RelationalParser.TransactionOptionContext ctx) { + public Object visitTransactionOption(RelationalParser.TransactionOptionContext ctx) { return getDelegate().visitTransactionOption(ctx); } - @Nonnull @Override - public Object visitTransactionLevel(@Nonnull RelationalParser.TransactionLevelContext ctx) { + public Object visitTransactionLevel(RelationalParser.TransactionLevelContext ctx) { return getDelegate().visitTransactionLevel(ctx); } - @Nonnull @Override - public Object visitPrepareStatement(@Nonnull RelationalParser.PrepareStatementContext ctx) { + public Object visitPrepareStatement(RelationalParser.PrepareStatementContext ctx) { return getDelegate().visitPrepareStatement(ctx); } - @Nonnull @Override - public Object visitExecuteStatement(@Nonnull RelationalParser.ExecuteStatementContext ctx) { + public Object visitExecuteStatement(RelationalParser.ExecuteStatementContext ctx) { return getDelegate().visitExecuteStatement(ctx); } - @Nonnull @Override - public QueryPlan.MetadataQueryPlan visitShowDatabasesStatement(@Nonnull RelationalParser.ShowDatabasesStatementContext ctx) { + public QueryPlan.MetadataQueryPlan visitShowDatabasesStatement(RelationalParser.ShowDatabasesStatementContext ctx) { return getDelegate().visitShowDatabasesStatement(ctx); } - @Nonnull @Override - public QueryPlan.MetadataQueryPlan visitShowSchemaTemplatesStatement(@Nonnull RelationalParser.ShowSchemaTemplatesStatementContext ctx) { + public QueryPlan.MetadataQueryPlan visitShowSchemaTemplatesStatement(RelationalParser.ShowSchemaTemplatesStatementContext ctx) { return getDelegate().visitShowSchemaTemplatesStatement(ctx); } - @Nonnull @Override - public Object visitSetVariable(@Nonnull RelationalParser.SetVariableContext ctx) { + public Object visitSetVariable(RelationalParser.SetVariableContext ctx) { return getDelegate().visitSetVariable(ctx); } - @Nonnull @Override - public Object visitSetCharset(@Nonnull RelationalParser.SetCharsetContext ctx) { + public Object visitSetCharset(RelationalParser.SetCharsetContext ctx) { return getDelegate().visitSetCharset(ctx); } - @Nonnull @Override - public Object visitSetNames(@Nonnull RelationalParser.SetNamesContext ctx) { + public Object visitSetNames(RelationalParser.SetNamesContext ctx) { return getDelegate().visitSetNames(ctx); } - @Nonnull @Override - public Object visitSetTransaction(@Nonnull RelationalParser.SetTransactionContext ctx) { + public Object visitSetTransaction(RelationalParser.SetTransactionContext ctx) { return getDelegate().visitSetTransaction(ctx); } - @Nonnull @Override - public Object visitSetAutocommit(@Nonnull RelationalParser.SetAutocommitContext ctx) { + public Object visitSetAutocommit(RelationalParser.SetAutocommitContext ctx) { return getDelegate().visitSetAutocommit(ctx); } - @Nonnull @Override - public Object visitSetNewValueInsideTrigger(@Nonnull RelationalParser.SetNewValueInsideTriggerContext ctx) { + public Object visitSetNewValueInsideTrigger(RelationalParser.SetNewValueInsideTriggerContext ctx) { return getDelegate().visitSetNewValueInsideTrigger(ctx); } - @Nonnull @Override - public Object visitVariableClause(@Nonnull RelationalParser.VariableClauseContext ctx) { + public Object visitVariableClause(RelationalParser.VariableClauseContext ctx) { return getDelegate().visitVariableClause(ctx); } - @Nonnull @Override - public Object visitKillStatement(@Nonnull RelationalParser.KillStatementContext ctx) { + public Object visitKillStatement(RelationalParser.KillStatementContext ctx) { return getDelegate().visitKillStatement(ctx); } - @Nonnull @Override - public Object visitResetStatement(@Nonnull RelationalParser.ResetStatementContext ctx) { + public Object visitResetStatement(RelationalParser.ResetStatementContext ctx) { return getDelegate().visitResetStatement(ctx); } - @Nonnull @Override - public Object visitExecuteContinuationStatement(@Nonnull RelationalParser.ExecuteContinuationStatementContext ctx) { + public Object visitExecuteContinuationStatement(RelationalParser.ExecuteContinuationStatementContext ctx) { return getDelegate().visitExecuteContinuationStatement(ctx); } - @Nonnull @Override - public QueryPlan visitCopyExportStatement(@Nonnull RelationalParser.CopyExportStatementContext ctx) { + public QueryPlan visitCopyExportStatement(RelationalParser.CopyExportStatementContext ctx) { return (QueryPlan) getDelegate().visitCopyExportStatement(ctx); } - @Nonnull @Override - public QueryPlan visitCopyImportStatement(@Nonnull RelationalParser.CopyImportStatementContext ctx) { + public QueryPlan visitCopyImportStatement(RelationalParser.CopyImportStatementContext ctx) { return (QueryPlan) getDelegate().visitCopyImportStatement(ctx); } - @Nonnull @Override - public Object visitIncarnationOption(@Nonnull RelationalParser.IncarnationOptionContext ctx) { + public Object visitIncarnationOption(RelationalParser.IncarnationOptionContext ctx) { return getDelegate().visitIncarnationOption(ctx); } - @Nonnull @Override - public Object visitTableIndexes(@Nonnull RelationalParser.TableIndexesContext ctx) { + public Object visitTableIndexes(RelationalParser.TableIndexesContext ctx) { return getDelegate().visitTableIndexes(ctx); } - @Nonnull @Override - public Object visitLoadedTableIndexes(@Nonnull RelationalParser.LoadedTableIndexesContext ctx) { + public Object visitLoadedTableIndexes(RelationalParser.LoadedTableIndexesContext ctx) { return getDelegate().visitLoadedTableIndexes(ctx); } - @Nonnull @Override - public QueryPlan.MetadataQueryPlan visitSimpleDescribeSchemaStatement(@Nonnull RelationalParser.SimpleDescribeSchemaStatementContext ctx) { + public QueryPlan.MetadataQueryPlan visitSimpleDescribeSchemaStatement(RelationalParser.SimpleDescribeSchemaStatementContext ctx) { return getDelegate().visitSimpleDescribeSchemaStatement(ctx); } - @Nonnull @Override - public QueryPlan.MetadataQueryPlan visitSimpleDescribeSchemaTemplateStatement(@Nonnull RelationalParser.SimpleDescribeSchemaTemplateStatementContext ctx) { + public QueryPlan.MetadataQueryPlan visitSimpleDescribeSchemaTemplateStatement(RelationalParser.SimpleDescribeSchemaTemplateStatementContext ctx) { return getDelegate().visitSimpleDescribeSchemaTemplateStatement(ctx); } - @Nonnull @Override - public QueryPlan.LogicalQueryPlan visitFullDescribeStatement(@Nonnull RelationalParser.FullDescribeStatementContext ctx) { + public QueryPlan.LogicalQueryPlan visitFullDescribeStatement(RelationalParser.FullDescribeStatementContext ctx) { return getDelegate().visitFullDescribeStatement(ctx); } - @Nonnull @Override - public Object visitHelpStatement(@Nonnull RelationalParser.HelpStatementContext ctx) { + public Object visitHelpStatement(RelationalParser.HelpStatementContext ctx) { return getDelegate().visitHelpStatement(ctx); } - @Nonnull @Override - public Object visitDescribeStatements(@Nonnull RelationalParser.DescribeStatementsContext ctx) { + public Object visitDescribeStatements(RelationalParser.DescribeStatementsContext ctx) { return getDelegate().visitDescribeStatements(ctx); } - @Nonnull @Override - public Object visitDescribeConnection(@Nonnull RelationalParser.DescribeConnectionContext ctx) { + public Object visitDescribeConnection(RelationalParser.DescribeConnectionContext ctx) { return getDelegate().visitDescribeConnection(ctx); } - @Nonnull @Override - public Identifier visitFullId(@Nonnull RelationalParser.FullIdContext ctx) { + public Identifier visitFullId(RelationalParser.FullIdContext ctx) { return getDelegate().visitFullId(ctx); } - @Nonnull @Override - public Expression visitUserDefinedMacroFunctionStatementBody(@Nonnull RelationalParser.UserDefinedMacroFunctionStatementBodyContext ctx) { + public Expression visitUserDefinedMacroFunctionStatementBody(RelationalParser.UserDefinedMacroFunctionStatementBodyContext ctx) { return getDelegate().visitUserDefinedMacroFunctionStatementBody(ctx); } - @Nonnull @Override - public Identifier visitTableName(@Nonnull RelationalParser.TableNameContext ctx) { + public Identifier visitTableName(RelationalParser.TableNameContext ctx) { return getDelegate().visitTableName(ctx); } - @Nonnull @Override - public Expression visitFullColumnName(@Nonnull RelationalParser.FullColumnNameContext ctx) { + public Expression visitFullColumnName(RelationalParser.FullColumnNameContext ctx) { return getDelegate().visitFullColumnName(ctx); } - @Nonnull @Override - public Identifier visitIndexColumnName(@Nonnull RelationalParser.IndexColumnNameContext ctx) { + public Identifier visitIndexColumnName(RelationalParser.IndexColumnNameContext ctx) { return getDelegate().visitIndexColumnName(ctx); } - @Nonnull @Override - public Identifier visitCharsetName(@Nonnull RelationalParser.CharsetNameContext ctx) { + public Identifier visitCharsetName(RelationalParser.CharsetNameContext ctx) { return getDelegate().visitCharsetName(ctx); } - @Nonnull @Override - public Identifier visitCollationName(@Nonnull RelationalParser.CollationNameContext ctx) { + public Identifier visitCollationName(RelationalParser.CollationNameContext ctx) { return getDelegate().visitCollationName(ctx); } - @Nonnull @Override - public Identifier visitUid(@Nonnull RelationalParser.UidContext ctx) { + public Identifier visitUid(RelationalParser.UidContext ctx) { return getDelegate().visitUid(ctx); } - @Nonnull @Override - public Identifier visitSimpleId(@Nonnull RelationalParser.SimpleIdContext ctx) { + public Identifier visitSimpleId(RelationalParser.SimpleIdContext ctx) { return getDelegate().visitSimpleId(ctx); } - @Nonnull @Override - public Object visitNullNotnull(@Nonnull RelationalParser.NullNotnullContext ctx) { + public Object visitNullNotnull(RelationalParser.NullNotnullContext ctx) { return getDelegate().visitNullNotnull(ctx); } - @Nonnull @Override - public Expression visitDecimalLiteral(@Nonnull RelationalParser.DecimalLiteralContext ctx) { + public Expression visitDecimalLiteral(RelationalParser.DecimalLiteralContext ctx) { return getDelegate().visitDecimalLiteral(ctx); } - @Nonnull @Override - public Expression visitStringLiteral(@Nonnull RelationalParser.StringLiteralContext ctx) { + public Expression visitStringLiteral(RelationalParser.StringLiteralContext ctx) { return getDelegate().visitStringLiteral(ctx); } - @Nonnull @Override - public Expression visitBooleanLiteral(@Nonnull RelationalParser.BooleanLiteralContext ctx) { + public Expression visitBooleanLiteral(RelationalParser.BooleanLiteralContext ctx) { return getDelegate().visitBooleanLiteral(ctx); } - @Nonnull @Override - public Expression visitBytesLiteral(@Nonnull RelationalParser.BytesLiteralContext ctx) { + public Expression visitBytesLiteral(RelationalParser.BytesLiteralContext ctx) { return getDelegate().visitBytesLiteral(ctx); } - @Nonnull @Override - public Expression visitNullLiteral(@Nonnull RelationalParser.NullLiteralContext ctx) { + public Expression visitNullLiteral(RelationalParser.NullLiteralContext ctx) { return getDelegate().visitNullLiteral(ctx); } - @Nonnull @Override - public Expression visitStringConstant(@Nonnull RelationalParser.StringConstantContext ctx) { + public Expression visitStringConstant(RelationalParser.StringConstantContext ctx) { return getDelegate().visitStringConstant(ctx); } - @Nonnull @Override - public Expression visitDecimalConstant(@Nonnull RelationalParser.DecimalConstantContext ctx) { + public Expression visitDecimalConstant(RelationalParser.DecimalConstantContext ctx) { return getDelegate().visitDecimalConstant(ctx); } - @Nonnull @Override - public Expression visitNegativeDecimalConstant(@Nonnull RelationalParser.NegativeDecimalConstantContext ctx) { + public Expression visitNegativeDecimalConstant(RelationalParser.NegativeDecimalConstantContext ctx) { return getDelegate().visitNegativeDecimalConstant(ctx); } - @Nonnull @Override - public Expression visitBytesConstant(@Nonnull RelationalParser.BytesConstantContext ctx) { + public Expression visitBytesConstant(RelationalParser.BytesConstantContext ctx) { return getDelegate().visitBytesConstant(ctx); } - @Nonnull @Override - public Expression visitBooleanConstant(@Nonnull RelationalParser.BooleanConstantContext ctx) { + public Expression visitBooleanConstant(RelationalParser.BooleanConstantContext ctx) { return getDelegate().visitBooleanConstant(ctx); } - @Nonnull @Override - public Expression visitBitStringConstant(@Nonnull RelationalParser.BitStringConstantContext ctx) { + public Expression visitBitStringConstant(RelationalParser.BitStringConstantContext ctx) { return getDelegate().visitBitStringConstant(ctx); } - @Nonnull @Override - public Expression visitNullConstant(@Nonnull RelationalParser.NullConstantContext ctx) { + public Expression visitNullConstant(RelationalParser.NullConstantContext ctx) { return getDelegate().visitNullConstant(ctx); } - @Nonnull @Override - public Object visitStringDataType(@Nonnull RelationalParser.StringDataTypeContext ctx) { + public Object visitStringDataType(RelationalParser.StringDataTypeContext ctx) { return getDelegate().visitStringDataType(ctx); } - @Nonnull @Override - public Object visitNationalStringDataType(@Nonnull RelationalParser.NationalStringDataTypeContext ctx) { + public Object visitNationalStringDataType(RelationalParser.NationalStringDataTypeContext ctx) { return getDelegate().visitNationalStringDataType(ctx); } - @Nonnull @Override - public Object visitNationalVaryingStringDataType(@Nonnull RelationalParser.NationalVaryingStringDataTypeContext ctx) { + public Object visitNationalVaryingStringDataType(RelationalParser.NationalVaryingStringDataTypeContext ctx) { return getDelegate().visitNationalVaryingStringDataType(ctx); } - @Nonnull @Override - public Object visitDimensionDataType(@Nonnull RelationalParser.DimensionDataTypeContext ctx) { + public Object visitDimensionDataType(RelationalParser.DimensionDataTypeContext ctx) { return getDelegate().visitDimensionDataType(ctx); } - @Nonnull @Override - public Object visitSimpleDataType(@Nonnull RelationalParser.SimpleDataTypeContext ctx) { + public Object visitSimpleDataType(RelationalParser.SimpleDataTypeContext ctx) { return getDelegate().visitSimpleDataType(ctx); } - @Nonnull @Override - public Object visitCollectionDataType(@Nonnull RelationalParser.CollectionDataTypeContext ctx) { + public Object visitCollectionDataType(RelationalParser.CollectionDataTypeContext ctx) { return getDelegate().visitCollectionDataType(ctx); } - @Nonnull @Override - public Object visitSpatialDataType(@Nonnull RelationalParser.SpatialDataTypeContext ctx) { + public Object visitSpatialDataType(RelationalParser.SpatialDataTypeContext ctx) { return getDelegate().visitSpatialDataType(ctx); } - @Nonnull @Override - public Object visitLongVarcharDataType(@Nonnull RelationalParser.LongVarcharDataTypeContext ctx) { + public Object visitLongVarcharDataType(RelationalParser.LongVarcharDataTypeContext ctx) { return getDelegate().visitLongVarcharDataType(ctx); } - @Nonnull @Override - public Object visitLongVarbinaryDataType(@Nonnull RelationalParser.LongVarbinaryDataTypeContext ctx) { + public Object visitLongVarbinaryDataType(RelationalParser.LongVarbinaryDataTypeContext ctx) { return getDelegate().visitLongVarbinaryDataType(ctx); } - @Nonnull @Override - public Object visitCollectionOptions(@Nonnull RelationalParser.CollectionOptionsContext ctx) { + public Object visitCollectionOptions(RelationalParser.CollectionOptionsContext ctx) { return getDelegate().visitCollectionOptions(ctx); } - @Nonnull @Override - public Object visitConvertedDataType(@Nonnull RelationalParser.ConvertedDataTypeContext ctx) { + public Object visitConvertedDataType(RelationalParser.ConvertedDataTypeContext ctx) { return getDelegate().visitConvertedDataType(ctx); } - @Nonnull @Override - public Object visitLengthOneDimension(@Nonnull RelationalParser.LengthOneDimensionContext ctx) { + public Object visitLengthOneDimension(RelationalParser.LengthOneDimensionContext ctx) { return getDelegate().visitLengthOneDimension(ctx); } - @Nonnull @Override - public Object visitLengthTwoDimension(@Nonnull RelationalParser.LengthTwoDimensionContext ctx) { + public Object visitLengthTwoDimension(RelationalParser.LengthTwoDimensionContext ctx) { return getDelegate().visitLengthTwoDimension(ctx); } - @Nonnull @Override - public Object visitLengthTwoOptionalDimension(@Nonnull RelationalParser.LengthTwoOptionalDimensionContext ctx) { + public Object visitLengthTwoOptionalDimension(RelationalParser.LengthTwoOptionalDimensionContext ctx) { return getDelegate().visitLengthTwoOptionalDimension(ctx); } - @Nonnull @Override - public List visitUidList(@Nonnull RelationalParser.UidListContext ctx) { + public List visitUidList(RelationalParser.UidListContext ctx) { return getDelegate().visitUidList(ctx); } - @Nonnull @Override - public Object visitUidWithNestings(@Nonnull RelationalParser.UidWithNestingsContext ctx) { + public Object visitUidWithNestings(RelationalParser.UidWithNestingsContext ctx) { return getDelegate().visitUidWithNestings(ctx); } - @Nonnull @Override - public CompatibleTypeEvolutionPredicate.FieldAccessTrieNode visitUidListWithNestingsInParens(@Nonnull RelationalParser.UidListWithNestingsInParensContext ctx) { + public CompatibleTypeEvolutionPredicate.FieldAccessTrieNode visitUidListWithNestingsInParens(RelationalParser.UidListWithNestingsInParensContext ctx) { return getDelegate().visitUidListWithNestingsInParens(ctx); } - @Nonnull @Override - public CompatibleTypeEvolutionPredicate.FieldAccessTrieNode visitUidListWithNestings(@Nonnull RelationalParser.UidListWithNestingsContext ctx) { + public CompatibleTypeEvolutionPredicate.FieldAccessTrieNode visitUidListWithNestings(RelationalParser.UidListWithNestingsContext ctx) { return getDelegate().visitUidListWithNestings(ctx); } - @Nonnull @Override - public Object visitTables(@Nonnull RelationalParser.TablesContext ctx) { + public Object visitTables(RelationalParser.TablesContext ctx) { return getDelegate().visitTables(ctx); } - @Nonnull @Override - public Object visitIndexColumnNames(@Nonnull RelationalParser.IndexColumnNamesContext ctx) { + public Object visitIndexColumnNames(RelationalParser.IndexColumnNamesContext ctx) { return getDelegate().visitIndexColumnNames(ctx); } - @Nonnull @Override - public Expressions visitExpressions(@Nonnull RelationalParser.ExpressionsContext ctx) { + public Expressions visitExpressions(RelationalParser.ExpressionsContext ctx) { return getDelegate().visitExpressions(ctx); } - @Nonnull @Override - public Object visitExpressionsWithDefaults(@Nonnull RelationalParser.ExpressionsWithDefaultsContext ctx) { + public Object visitExpressionsWithDefaults(RelationalParser.ExpressionsWithDefaultsContext ctx) { return getDelegate().visitExpressionsWithDefaults(ctx); } - @Nonnull @Override - public Expression visitRecordConstructorForInsert(@Nonnull RelationalParser.RecordConstructorForInsertContext ctx) { + public Expression visitRecordConstructorForInsert(RelationalParser.RecordConstructorForInsertContext ctx) { return getDelegate().visitRecordConstructorForInsert(ctx); } - @Nonnull @Override - public Expression visitRecordConstructorForInlineTable(@Nonnull RelationalParser.RecordConstructorForInlineTableContext ctx) { + public Expression visitRecordConstructorForInlineTable(RelationalParser.RecordConstructorForInlineTableContext ctx) { return getDelegate().visitRecordConstructorForInlineTable(ctx); } - @Nonnull @Override - public Expression visitRecordConstructor(@Nonnull RelationalParser.RecordConstructorContext ctx) { + public Expression visitRecordConstructor(RelationalParser.RecordConstructorContext ctx) { return getDelegate().visitRecordConstructor(ctx); } - @Nonnull @Override - public Object visitOfTypeClause(@Nonnull RelationalParser.OfTypeClauseContext ctx) { + public Object visitOfTypeClause(RelationalParser.OfTypeClauseContext ctx) { return getDelegate().visitOfTypeClause(ctx); } - @Nonnull @Override - public Expression visitArrayConstructor(@Nonnull RelationalParser.ArrayConstructorContext ctx) { + public Expression visitArrayConstructor(RelationalParser.ArrayConstructorContext ctx) { return getDelegate().visitArrayConstructor(ctx); } - @Nonnull @Override - public Object visitUserVariables(@Nonnull RelationalParser.UserVariablesContext ctx) { + public Object visitUserVariables(RelationalParser.UserVariablesContext ctx) { return getDelegate().visitUserVariables(ctx); } - @Nonnull @Override - public Object visitDefaultValue(@Nonnull RelationalParser.DefaultValueContext ctx) { + public Object visitDefaultValue(RelationalParser.DefaultValueContext ctx) { return getDelegate().visitDefaultValue(ctx); } - @Nonnull @Override - public Object visitCurrentTimestamp(@Nonnull RelationalParser.CurrentTimestampContext ctx) { + public Object visitCurrentTimestamp(RelationalParser.CurrentTimestampContext ctx) { return getDelegate().visitCurrentTimestamp(ctx); } - @Nonnull @Override - public Object visitExpressionOrDefault(@Nonnull RelationalParser.ExpressionOrDefaultContext ctx) { + public Object visitExpressionOrDefault(RelationalParser.ExpressionOrDefaultContext ctx) { return getDelegate().visitExpressionOrDefault(ctx); } - @Nonnull @Override - public Expression visitExpressionWithOptionalName(@Nonnull RelationalParser.ExpressionWithOptionalNameContext ctx) { + public Expression visitExpressionWithOptionalName(RelationalParser.ExpressionWithOptionalNameContext ctx) { return getDelegate().visitExpressionWithOptionalName(ctx); } @Nullable @Override - public Object visitIfExists(@Nonnull RelationalParser.IfExistsContext ctx) { + public Object visitIfExists(RelationalParser.IfExistsContext ctx) { return getDelegate().visitIfExists(ctx); } @Nullable @Override - public Object visitIfNotExists(@Nonnull RelationalParser.IfNotExistsContext ctx) { + public Object visitIfNotExists(RelationalParser.IfNotExistsContext ctx) { return getDelegate().visitIfNotExists(ctx); } - @Nonnull @Override - public Object visitUserDefinedScalarFunctionName(@Nonnull RelationalParser.UserDefinedScalarFunctionNameContext ctx) { + public Object visitUserDefinedScalarFunctionName(RelationalParser.UserDefinedScalarFunctionNameContext ctx) { return getDelegate().visitUserDefinedScalarFunctionName(ctx); } - @Nonnull @Override - public Expression visitUserDefinedScalarFunctionCall(@Nonnull RelationalParser.UserDefinedScalarFunctionCallContext ctx) { + public Expression visitUserDefinedScalarFunctionCall(RelationalParser.UserDefinedScalarFunctionCallContext ctx) { return getDelegate().visitUserDefinedScalarFunctionCall(ctx); } - @Nonnull @Override - public Expression visitAggregateFunctionCall(@Nonnull RelationalParser.AggregateFunctionCallContext ctx) { + public Expression visitAggregateFunctionCall(RelationalParser.AggregateFunctionCallContext ctx) { return getDelegate().visitAggregateFunctionCall(ctx); } - @Nonnull @Override - public Expression visitNonAggregateFunctionCall(@Nonnull RelationalParser.NonAggregateFunctionCallContext ctx) { + public Expression visitNonAggregateFunctionCall(RelationalParser.NonAggregateFunctionCallContext ctx) { return getDelegate().visitNonAggregateFunctionCall(ctx); } - @Nonnull @Override - public Object visitSpecificFunctionCall(@Nonnull RelationalParser.SpecificFunctionCallContext ctx) { + public Object visitSpecificFunctionCall(RelationalParser.SpecificFunctionCallContext ctx) { return getDelegate().visitSpecificFunctionCall(ctx); } - @Nonnull @Override - public Expression visitScalarFunctionCall(@Nonnull RelationalParser.ScalarFunctionCallContext ctx) { + public Expression visitScalarFunctionCall(RelationalParser.ScalarFunctionCallContext ctx) { return getDelegate().visitScalarFunctionCall(ctx); } - @Nonnull @Override - public Object visitSimpleFunctionCall(@Nonnull RelationalParser.SimpleFunctionCallContext ctx) { + public Object visitSimpleFunctionCall(RelationalParser.SimpleFunctionCallContext ctx) { return getDelegate().visitSimpleFunctionCall(ctx); } - @Nonnull @Override - public Object visitDataTypeFunctionCall(@Nonnull RelationalParser.DataTypeFunctionCallContext ctx) { + public Object visitDataTypeFunctionCall(RelationalParser.DataTypeFunctionCallContext ctx) { return getDelegate().visitDataTypeFunctionCall(ctx); } - @Nonnull @Override - public Object visitValuesFunctionCall(@Nonnull RelationalParser.ValuesFunctionCallContext ctx) { + public Object visitValuesFunctionCall(RelationalParser.ValuesFunctionCallContext ctx) { return getDelegate().visitValuesFunctionCall(ctx); } - @Nonnull @Override - public Object visitCaseExpressionFunctionCall(@Nonnull RelationalParser.CaseExpressionFunctionCallContext ctx) { + public Object visitCaseExpressionFunctionCall(RelationalParser.CaseExpressionFunctionCallContext ctx) { return getDelegate().visitCaseExpressionFunctionCall(ctx); } - @Nonnull @Override - public Expression visitCaseFunctionCall(@Nonnull RelationalParser.CaseFunctionCallContext ctx) { + public Expression visitCaseFunctionCall(RelationalParser.CaseFunctionCallContext ctx) { return getDelegate().visitCaseFunctionCall(ctx); } - @Nonnull @Override - public Object visitCharFunctionCall(@Nonnull RelationalParser.CharFunctionCallContext ctx) { + public Object visitCharFunctionCall(RelationalParser.CharFunctionCallContext ctx) { return getDelegate().visitCharFunctionCall(ctx); } - @Nonnull @Override - public Object visitPositionFunctionCall(@Nonnull RelationalParser.PositionFunctionCallContext ctx) { + public Object visitPositionFunctionCall(RelationalParser.PositionFunctionCallContext ctx) { return getDelegate().visitPositionFunctionCall(ctx); } - @Nonnull @Override - public Object visitSubstrFunctionCall(@Nonnull RelationalParser.SubstrFunctionCallContext ctx) { + public Object visitSubstrFunctionCall(RelationalParser.SubstrFunctionCallContext ctx) { return getDelegate().visitSubstrFunctionCall(ctx); } - @Nonnull @Override - public Object visitTrimFunctionCall(@Nonnull RelationalParser.TrimFunctionCallContext ctx) { + public Object visitTrimFunctionCall(RelationalParser.TrimFunctionCallContext ctx) { return getDelegate().visitTrimFunctionCall(ctx); } - @Nonnull @Override - public Object visitWeightFunctionCall(@Nonnull RelationalParser.WeightFunctionCallContext ctx) { + public Object visitWeightFunctionCall(RelationalParser.WeightFunctionCallContext ctx) { return getDelegate().visitWeightFunctionCall(ctx); } - @Nonnull @Override - public Object visitExtractFunctionCall(@Nonnull RelationalParser.ExtractFunctionCallContext ctx) { + public Object visitExtractFunctionCall(RelationalParser.ExtractFunctionCallContext ctx) { return getDelegate().visitExtractFunctionCall(ctx); } - @Nonnull @Override - public Object visitGetFormatFunctionCall(@Nonnull RelationalParser.GetFormatFunctionCallContext ctx) { + public Object visitGetFormatFunctionCall(RelationalParser.GetFormatFunctionCallContext ctx) { return getDelegate().visitGetFormatFunctionCall(ctx); } - @Nonnull @Override - public Object visitCaseFuncAlternative(@Nonnull RelationalParser.CaseFuncAlternativeContext ctx) { + public Object visitCaseFuncAlternative(RelationalParser.CaseFuncAlternativeContext ctx) { return getDelegate().visitCaseFuncAlternative(ctx); } - @Nonnull @Override - public Object visitLevelWeightList(@Nonnull RelationalParser.LevelWeightListContext ctx) { + public Object visitLevelWeightList(RelationalParser.LevelWeightListContext ctx) { return getDelegate().visitLevelWeightList(ctx); } - @Nonnull @Override - public Object visitLevelWeightRange(@Nonnull RelationalParser.LevelWeightRangeContext ctx) { + public Object visitLevelWeightRange(RelationalParser.LevelWeightRangeContext ctx) { return getDelegate().visitLevelWeightRange(ctx); } - @Nonnull @Override - public Object visitLevelInWeightListElement(@Nonnull RelationalParser.LevelInWeightListElementContext ctx) { + public Object visitLevelInWeightListElement(RelationalParser.LevelInWeightListElementContext ctx) { return getDelegate().visitLevelInWeightListElement(ctx); } - @Nonnull @Override - public Expression visitAggregateWindowedFunction(@Nonnull RelationalParser.AggregateWindowedFunctionContext ctx) { + public Expression visitAggregateWindowedFunction(RelationalParser.AggregateWindowedFunctionContext ctx) { return getDelegate().visitAggregateWindowedFunction(ctx); } - @Nonnull @Override - public Boolean visitNullTreatmentClause(@Nonnull RelationalParser.NullTreatmentClauseContext ctx) { + public Boolean visitNullTreatmentClause(RelationalParser.NullTreatmentClauseContext ctx) { return getDelegate().visitNullTreatmentClause(ctx); } - @Nonnull @Override - public Expression visitNonAggregateWindowedFunction(@Nonnull RelationalParser.NonAggregateWindowedFunctionContext ctx) { + public Expression visitNonAggregateWindowedFunction(RelationalParser.NonAggregateWindowedFunctionContext ctx) { return getDelegate().visitNonAggregateWindowedFunction(ctx); } - @Nonnull @Override - public WindowSpecExpression visitOverClause(@Nonnull RelationalParser.OverClauseContext ctx) { + public WindowSpecExpression visitOverClause(RelationalParser.OverClauseContext ctx) { return getDelegate().visitOverClause(ctx); } - @Nonnull @Override - public Object visitWindowName(@Nonnull RelationalParser.WindowNameContext ctx) { + public Object visitWindowName(RelationalParser.WindowNameContext ctx) { return getDelegate().visitWindowName(ctx); } - @Nonnull @Override public Object visitWindowSpec(final RelationalParser.WindowSpecContext ctx) { return getDelegate().visitWindowSpec(ctx); } - @Nonnull @Override public Expressions visitWindowOptionsClause(final RelationalParser.WindowOptionsClauseContext ctx) { return getDelegate().visitWindowOptionsClause(ctx); } - @Nonnull @Override public Expression visitWindowOption(final RelationalParser.WindowOptionContext ctx) { return getDelegate().visitWindowOption(ctx); } - @Nonnull @Override public Expressions visitPartitionClause(final RelationalParser.PartitionClauseContext ctx) { return getDelegate().visitPartitionClause(ctx); } - @Nonnull @Override - public Object visitScalarFunctionName(@Nonnull RelationalParser.ScalarFunctionNameContext ctx) { + public Object visitScalarFunctionName(RelationalParser.ScalarFunctionNameContext ctx) { return getDelegate().visitScalarFunctionName(ctx); } - @Nonnull @Override - public Expressions visitFunctionArgs(@Nonnull RelationalParser.FunctionArgsContext ctx) { + public Expressions visitFunctionArgs(RelationalParser.FunctionArgsContext ctx) { return getDelegate().visitFunctionArgs(ctx); } - @Nonnull @Override - public Object visitFunctionArg(@Nonnull RelationalParser.FunctionArgContext ctx) { + public Object visitFunctionArg(RelationalParser.FunctionArgContext ctx) { return getDelegate().visitFunctionArg(ctx); } @@ -1522,92 +1319,78 @@ public Expression visitNamedFunctionArg(final RelationalParser.NamedFunctionArgC return getDelegate().visitNamedFunctionArg(ctx); } - @Nonnull @Override - public Expression visitNotExpression(@Nonnull RelationalParser.NotExpressionContext ctx) { + public Expression visitNotExpression(RelationalParser.NotExpressionContext ctx) { return getDelegate().visitNotExpression(ctx); } - @Nonnull @Override - public Expression visitLogicalExpression(@Nonnull RelationalParser.LogicalExpressionContext ctx) { + public Expression visitLogicalExpression(RelationalParser.LogicalExpressionContext ctx) { return getDelegate().visitLogicalExpression(ctx); } - @Nonnull @Override - public Expression visitPredicatedExpression(@Nonnull RelationalParser.PredicatedExpressionContext ctx) { + public Expression visitPredicatedExpression(RelationalParser.PredicatedExpressionContext ctx) { return getDelegate().visitPredicatedExpression(ctx); } - @Nonnull @Override - public Expression visitBinaryComparisonPredicate(@Nonnull RelationalParser.BinaryComparisonPredicateContext ctx) { + public Expression visitBinaryComparisonPredicate(RelationalParser.BinaryComparisonPredicateContext ctx) { return getDelegate().visitBinaryComparisonPredicate(ctx); } @Override - public Expression visitSubscriptExpression(@Nonnull RelationalParser.SubscriptExpressionContext ctx) { + public Expression visitSubscriptExpression(RelationalParser.SubscriptExpressionContext ctx) { return getDelegate().visitSubscriptExpression(ctx); } - @Nonnull @Override - public Expression visitInList(@Nonnull RelationalParser.InListContext ctx) { + public Expression visitInList(RelationalParser.InListContext ctx) { return getDelegate().visitInList(ctx); } - @Nonnull @Override - public Object visitConstantExpressionAtom(@Nonnull RelationalParser.ConstantExpressionAtomContext ctx) { + public Object visitConstantExpressionAtom(RelationalParser.ConstantExpressionAtomContext ctx) { return getDelegate().visitConstantExpressionAtom(ctx); } - @Nonnull @Override - public Expression visitFunctionCallExpressionAtom(@Nonnull RelationalParser.FunctionCallExpressionAtomContext ctx) { + public Expression visitFunctionCallExpressionAtom(RelationalParser.FunctionCallExpressionAtomContext ctx) { return getDelegate().visitFunctionCallExpressionAtom(ctx); } - @Nonnull @Override - public Object visitFullColumnNameExpressionAtom(@Nonnull RelationalParser.FullColumnNameExpressionAtomContext ctx) { + public Object visitFullColumnNameExpressionAtom(RelationalParser.FullColumnNameExpressionAtomContext ctx) { return getDelegate().visitFullColumnNameExpressionAtom(ctx); } - @Nonnull @Override - public Expression visitBitExpressionAtom(@Nonnull RelationalParser.BitExpressionAtomContext ctx) { + public Expression visitBitExpressionAtom(RelationalParser.BitExpressionAtomContext ctx) { return getDelegate().visitBitExpressionAtom(ctx); } - @Nonnull @Override - public Expression visitPreparedStatementParameterAtom(@Nonnull RelationalParser.PreparedStatementParameterAtomContext ctx) { + public Expression visitPreparedStatementParameterAtom(RelationalParser.PreparedStatementParameterAtomContext ctx) { return getDelegate().visitPreparedStatementParameterAtom(ctx); } - @Nonnull @Override - public Object visitRecordConstructorExpressionAtom(@Nonnull RelationalParser.RecordConstructorExpressionAtomContext ctx) { + public Object visitRecordConstructorExpressionAtom(RelationalParser.RecordConstructorExpressionAtomContext ctx) { return getDelegate().visitRecordConstructorExpressionAtom(ctx); } - @Nonnull @Override - public Object visitArrayConstructorExpressionAtom(@Nonnull RelationalParser.ArrayConstructorExpressionAtomContext ctx) { + public Object visitArrayConstructorExpressionAtom(RelationalParser.ArrayConstructorExpressionAtomContext ctx) { return getDelegate().visitArrayConstructorExpressionAtom(ctx); } - @Nonnull @Override - public Expression visitMathExpressionAtom(@Nonnull RelationalParser.MathExpressionAtomContext ctx) { + public Expression visitMathExpressionAtom(RelationalParser.MathExpressionAtomContext ctx) { return getDelegate().visitMathExpressionAtom(ctx); } - @Nonnull @Override - public Expression visitExistsExpressionAtom(@Nonnull RelationalParser.ExistsExpressionAtomContext ctx) { + public Expression visitExistsExpressionAtom(RelationalParser.ExistsExpressionAtomContext ctx) { return getDelegate().visitExistsExpressionAtom(ctx); } @@ -1631,75 +1414,63 @@ public Object visitIsExpression(final RelationalParser.IsExpressionContext ctx) return getDelegate().visitIsExpression(ctx); } - @Nonnull @Override - public Expression visitPreparedStatementParameter(@Nonnull RelationalParser.PreparedStatementParameterContext ctx) { + public Expression visitPreparedStatementParameter(RelationalParser.PreparedStatementParameterContext ctx) { return getDelegate().visitPreparedStatementParameter(ctx); } - @Nonnull @Override - public Object visitUnaryOperator(@Nonnull RelationalParser.UnaryOperatorContext ctx) { + public Object visitUnaryOperator(RelationalParser.UnaryOperatorContext ctx) { return getDelegate().visitUnaryOperator(ctx); } - @Nonnull @Override - public Object visitComparisonOperator(@Nonnull RelationalParser.ComparisonOperatorContext ctx) { + public Object visitComparisonOperator(RelationalParser.ComparisonOperatorContext ctx) { return getDelegate().visitComparisonOperator(ctx); } - @Nonnull @Override - public Object visitLogicalOperator(@Nonnull RelationalParser.LogicalOperatorContext ctx) { + public Object visitLogicalOperator(RelationalParser.LogicalOperatorContext ctx) { return getDelegate().visitLogicalOperator(ctx); } - @Nonnull @Override - public Object visitBitOperator(@Nonnull RelationalParser.BitOperatorContext ctx) { + public Object visitBitOperator(RelationalParser.BitOperatorContext ctx) { return getDelegate().visitBitOperator(ctx); } - @Nonnull @Override - public Object visitMathOperator(@Nonnull RelationalParser.MathOperatorContext ctx) { + public Object visitMathOperator(RelationalParser.MathOperatorContext ctx) { return getDelegate().visitMathOperator(ctx); } - @Nonnull @Override - public Object visitJsonOperator(@Nonnull RelationalParser.JsonOperatorContext ctx) { + public Object visitJsonOperator(RelationalParser.JsonOperatorContext ctx) { return getDelegate().visitJsonOperator(ctx); } - @Nonnull @Override - public Object visitCharsetNameBase(@Nonnull RelationalParser.CharsetNameBaseContext ctx) { + public Object visitCharsetNameBase(RelationalParser.CharsetNameBaseContext ctx) { return getDelegate().visitCharsetNameBase(ctx); } - @Nonnull @Override - public Object visitIntervalTypeBase(@Nonnull RelationalParser.IntervalTypeBaseContext ctx) { + public Object visitIntervalTypeBase(RelationalParser.IntervalTypeBaseContext ctx) { return getDelegate().visitIntervalTypeBase(ctx); } - @Nonnull @Override - public Object visitKeywordsCanBeId(@Nonnull RelationalParser.KeywordsCanBeIdContext ctx) { + public Object visitKeywordsCanBeId(RelationalParser.KeywordsCanBeIdContext ctx) { return getDelegate().visitKeywordsCanBeId(ctx); } - @Nonnull @Override - public Object visitFunctionNameBase(@Nonnull RelationalParser.FunctionNameBaseContext ctx) { + public Object visitFunctionNameBase(RelationalParser.FunctionNameBaseContext ctx) { return getDelegate().visitFunctionNameBase(ctx); } - @Nonnull @Override - public Object visitFunctionNameKeyword(@Nonnull RelationalParser.FunctionNameKeywordContext ctx) { + public Object visitFunctionNameKeyword(RelationalParser.FunctionNameKeywordContext ctx) { return getDelegate().visitFunctionNameKeyword(ctx); } @@ -1714,7 +1485,7 @@ public Object visitChildren(RuleNode node) { } @Override - public Object visitOrderClause(@Nonnull RelationalParser.OrderClauseContext ctx) { + public Object visitOrderClause(RelationalParser.OrderClauseContext ctx) { return getDelegate().visitOrderClause(ctx); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/ExpressionVisitor.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/ExpressionVisitor.java index 55bd709cc6d..1f874dc2c17 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/ExpressionVisitor.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/ExpressionVisitor.java @@ -66,9 +66,7 @@ import com.google.protobuf.ZeroCopyByteString; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.Token; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -80,23 +78,25 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; +import static com.apple.foundationdb.record.query.plan.cascades.typing.Type.Record.Field; +import static com.apple.foundationdb.relational.generated.RelationalParser.FunctionArgsContext; + /** * This visits expression tree parse nodes and generates a corresponding {@link Expression}. */ @API(API.Status.EXPERIMENTAL) public final class ExpressionVisitor extends DelegatingVisitor { - private ExpressionVisitor(@Nonnull BaseVisitor baseVisitor) { + private ExpressionVisitor(BaseVisitor baseVisitor) { super(baseVisitor); } - @Nonnull - public static ExpressionVisitor of(@Nonnull BaseVisitor baseVisitor) { + public static ExpressionVisitor of(BaseVisitor baseVisitor) { return new ExpressionVisitor(baseVisitor); } @Override - public LogicalOperator visitTableFunction(@Nonnull RelationalParser.TableFunctionContext ctx) { + public LogicalOperator visitTableFunction(RelationalParser.TableFunctionContext ctx) { final var functionName = visitTableFunctionName(ctx.tableFunctionName()); final var arguments = ctx.namedOrUnnamedFunctionArgs() == null ? Expressions.empty() : @@ -126,15 +126,14 @@ public Expressions visitNamedOrUnnamedFunctionArgs(RelationalParser.NamedOrUnnam } @Override - public Expression visitNamedFunctionArg(@Nonnull final RelationalParser.NamedFunctionArgContext ctx) { + public Expression visitNamedFunctionArg(final RelationalParser.NamedFunctionArgContext ctx) { final var name = visitUid(ctx.key); final var expression = Assert.castUnchecked(visit(ctx.value), Expression.class); return expression.toNamedArgument(name); } - @Nonnull @Override - public Expression visitContinuationAtom(@Nonnull RelationalParser.ContinuationAtomContext ctx) { + public Expression visitContinuationAtom(RelationalParser.ContinuationAtomContext ctx) { return getDelegate().getPlanGenerationContext().withDisabledLiteralProcessing(() -> { final var continuationExpression = parseChild(ctx); SemanticAnalyzer.validateContinuation(continuationExpression); @@ -142,29 +141,25 @@ public Expression visitContinuationAtom(@Nonnull RelationalParser.ContinuationAt }); } - @Nonnull @Override - public Expression visitSelectStarElement(@Nonnull RelationalParser.SelectStarElementContext ignored) { + public Expression visitSelectStarElement(RelationalParser.SelectStarElementContext ignored) { return getDelegate().getSemanticAnalyzer().expandStar(Optional.empty(), getDelegate().getLogicalOperators()); } - @Nonnull @Override - public Expression visitSelectQualifierStarElement(@Nonnull RelationalParser.SelectQualifierStarElementContext ctx) { + public Expression visitSelectQualifierStarElement(RelationalParser.SelectQualifierStarElementContext ctx) { final var identifier = visitUid(ctx.uid()); // the semantics of valid correlations are extended to expanding a (correlated) qualified star. return getDelegate().getSemanticAnalyzer().expandStar(Optional.of(identifier), getDelegate().getLogicalOperatorsIncludingOuter()); } - @Nonnull @Override - public Expression visitFullColumnNameExpressionAtom(@Nonnull RelationalParser.FullColumnNameExpressionAtomContext fullColumnNameExpressionAtomContext) { + public Expression visitFullColumnNameExpressionAtom(RelationalParser.FullColumnNameExpressionAtomContext fullColumnNameExpressionAtomContext) { return Assert.castUnchecked(fullColumnNameExpressionAtomContext.fullColumnName().accept(this), Expression.class); } - @Nonnull @Override - public Expressions visitSelectElements(@Nonnull RelationalParser.SelectElementsContext selectElementsContext) { + public Expressions visitSelectElements(RelationalParser.SelectElementsContext selectElementsContext) { final var selectElements = Expressions.of(selectElementsContext.selectElement().stream() .map(selectElement -> Assert.castUnchecked(selectElement.accept(this), Expression.class)) .collect(ImmutableList.toImmutableList())); @@ -179,9 +174,8 @@ public Expressions visitSelectElements(@Nonnull RelationalParser.SelectElementsC return selectElements; } - @Nonnull @Override - public Expression visitSelectExpressionElement(@Nonnull RelationalParser.SelectExpressionElementContext selectExpressionElementContext) { + public Expression visitSelectExpressionElement(RelationalParser.SelectExpressionElementContext selectExpressionElementContext) { final var expression = Assert.castUnchecked(selectExpressionElementContext.expression().accept(this), Expression.class); if (selectExpressionElementContext.AS() != null) { final var expressionName = visitUid(selectExpressionElementContext.uid()); @@ -190,16 +184,14 @@ public Expression visitSelectExpressionElement(@Nonnull RelationalParser.SelectE return expression; } - @Nonnull @Override - public Expression visitFullColumnName(@Nonnull RelationalParser.FullColumnNameContext fullColumnNameContext) { + public Expression visitFullColumnName(RelationalParser.FullColumnNameContext fullColumnNameContext) { final var id = visitFullId(fullColumnNameContext.fullId()); return getDelegate().getSemanticAnalyzer().resolveIdentifier(id, getDelegate().getCurrentPlanFragment()); } - @Nonnull @Override - public List visitOrderByClause(@Nonnull RelationalParser.OrderByClauseContext orderByClauseContextContext) { + public List visitOrderByClause(RelationalParser.OrderByClauseContext orderByClauseContextContext) { if (!getDelegate().isTopLevel()) { Assert.failUnchecked(ErrorCode.UNSUPPORTED_OPERATION, "order by is not supported in subquery"); } @@ -211,26 +203,23 @@ public List visitOrderByClause(@Nonnull RelationalParser.Orde /** * Visits the individual expressions of an {@code ORDER BY} clause. */ - @Nonnull private List visitOrderByExpressions( - @Nonnull List contexts) { + List contexts) { return contexts.stream() .map(this::visitOrderByExpression) .collect(ImmutableList.toImmutableList()); } - @Nonnull @Override - public OrderByExpression visitOrderByExpression(@Nonnull RelationalParser.OrderByExpressionContext orderByExpressionContext) { + public OrderByExpression visitOrderByExpression(RelationalParser.OrderByExpressionContext orderByExpressionContext) { final var expression = Assert.castUnchecked(orderByExpressionContext.expression().accept(this), Expression.class); final var descending = ParseHelpers.isDescending(orderByExpressionContext.orderClause()); final var nullsLast = ParseHelpers.isNullsLast(orderByExpressionContext.orderClause(), descending); return OrderByExpression.of(expression, descending, nullsLast); } - @Nonnull @Override - public NonnullPair visitInlineTableDefinition(@Nonnull RelationalParser.InlineTableDefinitionContext ctx) { + public NonnullPair visitInlineTableDefinition(RelationalParser.InlineTableDefinitionContext ctx) { final var tableId = visitTableName(ctx.tableName()); final var columnIdTrie = visitUidListWithNestingsInParens(ctx.uidListWithNestingsInParens()); int columnCount = Objects.requireNonNull(columnIdTrie.getThis().getChildrenMap()).size(); @@ -244,7 +233,7 @@ public NonnullPair return NonnullPair.of(tableId.getName(), columnIdTrie); } - private static RecordLayerColumn toColumn(@Nonnull FieldValue.ResolvedAccessor field, @Nonnull CompatibleTypeEvolutionPredicate.FieldAccessTrieNode columnIdTrie) { + private static RecordLayerColumn toColumn(FieldValue.ResolvedAccessor field, CompatibleTypeEvolutionPredicate.FieldAccessTrieNode columnIdTrie) { final var columnName = field.getName(); final var builder = RecordLayerColumn.newBuilder().setName(columnName).setIndex(field.getOrdinal()); if (columnIdTrie.getChildrenMap() == null) { @@ -260,15 +249,13 @@ private static RecordLayerColumn toColumn(@Nonnull FieldValue.ResolvedAccessor f return builder.build(); } - @Nonnull @Override - public Expressions visitGroupByClause(@Nonnull RelationalParser.GroupByClauseContext groupByClauseContext) { + public Expressions visitGroupByClause(RelationalParser.GroupByClauseContext groupByClauseContext) { return Expressions.of(groupByClauseContext.groupByItem().stream().map(this::visitGroupByItem).collect(ImmutableList.toImmutableList())); } - @Nonnull @Override - public Expression visitGroupByItem(@Nonnull RelationalParser.GroupByItemContext groupByItemContext) { + public Expression visitGroupByItem(RelationalParser.GroupByItemContext groupByItemContext) { Assert.isNullUnchecked(groupByItemContext.order, ErrorCode.UNSUPPORTED_QUERY, "ordering grouping column is not supported"); final var expression = Assert.castUnchecked(groupByItemContext.expression().accept(this), Expression.class); if (groupByItemContext.uid() != null) { @@ -278,15 +265,13 @@ public Expression visitGroupByItem(@Nonnull RelationalParser.GroupByItemContext return expression; } - @Nonnull @Override - public Expression visitNonAggregateFunctionCall(@Nonnull final RelationalParser.NonAggregateFunctionCallContext ctx) { + public Expression visitNonAggregateFunctionCall(final RelationalParser.NonAggregateFunctionCallContext ctx) { return getDelegate().visitNonAggregateWindowedFunction(ctx.nonAggregateWindowedFunction()); } - @Nonnull @Override - public Expression visitNonAggregateWindowedFunction(@Nonnull final RelationalParser.NonAggregateWindowedFunctionContext windowedFunctionContext) { + public Expression visitNonAggregateWindowedFunction(final RelationalParser.NonAggregateWindowedFunctionContext windowedFunctionContext) { final String functionName = windowedFunctionContext.functionName.getText(); final WindowSpecExpression windowSpecExpression = getDelegate().visitOverClause(windowedFunctionContext.overClause()); @@ -302,37 +287,34 @@ public Expression visitNonAggregateWindowedFunction(@Nonnull final RelationalPar .resolveWindowFunction(functionName, true, windowSpecExpression, Expressions.empty()); } - @Nonnull @Override - public WindowSpecExpression visitOverClause(@Nonnull final RelationalParser.OverClauseContext ctx) { + public WindowSpecExpression visitOverClause(final RelationalParser.OverClauseContext ctx) { Assert.isNullUnchecked(ctx.windowName(), ErrorCode.UNSUPPORTED_QUERY, "named window functions not supported"); - @Nullable final var partitionClause = ctx.windowSpec().partitionClause(); + final var partitionClause = ctx.windowSpec().partitionClause(); final Expressions partitions = partitionClause == null ? Expressions.empty() : getDelegate().visitPartitionClause(partitionClause); - @Nullable final var orderByClause = ctx.windowSpec().orderByClause(); + final var orderByClause = ctx.windowSpec().orderByClause(); // Parse ORDER BY expressions directly — the isTopLevel() check in visitOrderByClause // is for query-level ORDER BY and does not apply inside OVER clauses. final List orderByExpressions = orderByClause == null ? ImmutableList.of() : visitOrderByExpressions(orderByClause.orderByExpression()); - @Nullable final var windowOptionsClause = ctx.windowSpec().windowOptionsClause(); + final var windowOptionsClause = ctx.windowSpec().windowOptionsClause(); final Expressions windowOptions = windowOptionsClause == null ? Expressions.empty() : getDelegate().visitWindowOptionsClause(windowOptionsClause); return WindowSpecExpression.of(partitions, orderByExpressions, windowOptions); } - @Nonnull @Override public Expressions visitWindowOptionsClause(final RelationalParser.WindowOptionsClauseContext ctx) { return Expressions.of(ImmutableSet.copyOf(ctx.windowOption().stream().map(option -> getDelegate().visitWindowOption(option)) .collect(ImmutableList.toImmutableList()))); } - @Nonnull @Override - public Expressions visitPartitionClause(@Nonnull final RelationalParser.PartitionClauseContext ctx) { + public Expressions visitPartitionClause(final RelationalParser.PartitionClauseContext ctx) { final var partitionByExpressions = ctx.fullId().stream() .map(fullId -> getDelegate().getSemanticAnalyzer() .resolveIdentifier(visitFullId(fullId), getDelegate().getCurrentPlanFragment())) @@ -340,7 +322,6 @@ public Expressions visitPartitionClause(@Nonnull final RelationalParser.Partitio return Expressions.of(partitionByExpressions); } - @Nonnull @Override public Expression visitWindowOption(final RelationalParser.WindowOptionContext ctx) { if (ctx.EF_SEARCH() != null) { @@ -354,15 +335,13 @@ public Expression visitWindowOption(final RelationalParser.WindowOptionContext c throw Assert.failUnchecked(ErrorCode.INTERNAL_ERROR, "unexpected option " + ctx.getText()); } - @Nonnull @Override - public Expression visitAggregateFunctionCall(@Nonnull RelationalParser.AggregateFunctionCallContext functionCon) { + public Expression visitAggregateFunctionCall(RelationalParser.AggregateFunctionCallContext functionCon) { return visitAggregateWindowedFunction(functionCon.aggregateWindowedFunction()); } - @Nonnull @Override - public Expression visitAggregateWindowedFunction(@Nonnull RelationalParser.AggregateWindowedFunctionContext functionContext) { + public Expression visitAggregateWindowedFunction(RelationalParser.AggregateWindowedFunctionContext functionContext) { final Token functionName = functionContext.functionName; final String name = functionName.getText(); @@ -424,19 +403,17 @@ public Expression visitAggregateWindowedFunction(@Nonnull RelationalParser.Aggre return getDelegate().resolveFunction(name, arguments); } - @Nonnull @Override - public Boolean visitNullTreatmentClause(@Nonnull final RelationalParser.NullTreatmentClauseContext ctx) { + public Boolean visitNullTreatmentClause(final RelationalParser.NullTreatmentClauseContext ctx) { return ctx.nullTreatment.getType() == RelationalParser.IGNORE; } - @Nonnull @Override - public Expression visitScalarFunctionCall(@Nonnull RelationalParser.ScalarFunctionCallContext ctx) { + public Expression visitScalarFunctionCall(RelationalParser.ScalarFunctionCallContext ctx) { final var functionName = ctx.scalarFunctionName().getText(); // special case for user-defined functions where we want to exclude the first argument from // being literal-stripped. - @Nonnull Expressions arguments; + Expressions arguments; boolean isUdf = getDelegate().getSemanticAnalyzer().isJavaCallFunction(functionName); if (isUdf) { final var argumentNodes = ctx.functionArgs().children.stream() @@ -460,9 +437,8 @@ public Expression visitScalarFunctionCall(@Nonnull RelationalParser.ScalarFuncti return getDelegate().resolveFunction(functionName, arguments.asList().toArray(new Expression[0])); } - @Nonnull @Override - public Expression visitUserDefinedScalarFunctionCall(@Nonnull RelationalParser.UserDefinedScalarFunctionCallContext ctx) { + public Expression visitUserDefinedScalarFunctionCall(RelationalParser.UserDefinedScalarFunctionCallContext ctx) { final var functionName = Identifier.of(getDelegate().normalizeString(ctx.userDefinedScalarFunctionName().getText())); Expressions arguments = ctx.namedOrUnnamedFunctionArgs() == null ? Expressions.empty() : @@ -470,9 +446,8 @@ public Expression visitUserDefinedScalarFunctionCall(@Nonnull RelationalParser.U return getDelegate().resolveFunction(functionName.getName(), arguments.asList().toArray(new Expression[0])); } - @Nonnull @Override - public Expression visitCaseFunctionCall(@Nonnull RelationalParser.CaseFunctionCallContext ctx) { + public Expression visitCaseFunctionCall(RelationalParser.CaseFunctionCallContext ctx) { final ImmutableList.Builder implications = ImmutableList.builder(); final ImmutableList.Builder pickerValues = ImmutableList.builder(); for (final var caseAlternative : ctx.caseFuncAlternative()) { @@ -494,9 +469,8 @@ public Expression visitCaseFunctionCall(@Nonnull RelationalParser.CaseFunctionCa return getDelegate().resolveFunction("__pick_value", arguments.build().toArray(new Expression[0])); } - @Nonnull @Override - public Expression visitDataTypeFunctionCall(@Nonnull RelationalParser.DataTypeFunctionCallContext ctx) { + public Expression visitDataTypeFunctionCall(RelationalParser.DataTypeFunctionCallContext ctx) { if (ctx.CAST() != null) { final var sourceExpression = Assert.castUnchecked(ctx.expression().accept(this), Expression.class); final var isRepeated = ctx.convertedDataType().ARRAY() != null; @@ -514,21 +488,18 @@ public Expression visitDataTypeFunctionCall(@Nonnull RelationalParser.DataTypeFu return null; } - @Nonnull @Override - public Expression visitFunctionCallExpressionAtom(@Nonnull RelationalParser.FunctionCallExpressionAtomContext ctx) { + public Expression visitFunctionCallExpressionAtom(RelationalParser.FunctionCallExpressionAtomContext ctx) { return parseChild(ctx); } - @Nonnull @Override - public Expression visitFunctionArg(@Nonnull RelationalParser.FunctionArgContext functionArgContext) { + public Expression visitFunctionArg(RelationalParser.FunctionArgContext functionArgContext) { return Assert.castUnchecked(functionArgContext.expression().accept(this), Expression.class); } - @Nonnull @Override - public Expressions visitFunctionArgs(@Nullable RelationalParser.FunctionArgsContext ctx) { + public Expressions visitFunctionArgs(@Nullable FunctionArgsContext ctx) { if (ctx == null) { return Expressions.of(List.of()); } else { @@ -536,21 +507,18 @@ public Expressions visitFunctionArgs(@Nullable RelationalParser.FunctionArgsCont } } - @Nonnull @Override - public Expression visitHavingClause(@Nonnull RelationalParser.HavingClauseContext havingClauseContext) { + public Expression visitHavingClause(RelationalParser.HavingClauseContext havingClauseContext) { return Assert.castUnchecked(havingClauseContext.expression().accept(this), Expression.class); } - @Nonnull @Override - public Expression visitPreparedStatementParameterAtom(@Nonnull RelationalParser.PreparedStatementParameterAtomContext ctx) { + public Expression visitPreparedStatementParameterAtom(RelationalParser.PreparedStatementParameterAtomContext ctx) { return visitPreparedStatementParameter(ctx.preparedStatementParameter()); } - @Nonnull @Override - public Expression visitPreparedStatementParameter(@Nonnull RelationalParser.PreparedStatementParameterContext ctx) { + public Expression visitPreparedStatementParameter(RelationalParser.PreparedStatementParameterContext ctx) { final var tokenIndex = ctx.getStart().getTokenIndex(); final Value value; if (ctx.QUESTION() != null) { @@ -563,24 +531,21 @@ public Expression visitPreparedStatementParameter(@Nonnull RelationalParser.Prep return Expression.ofUnnamed(type, value); } - @Nonnull @Override - public Expression visitNotExpression(@Nonnull RelationalParser.NotExpressionContext ctx) { + public Expression visitNotExpression(RelationalParser.NotExpressionContext ctx) { final var argument = Assert.castUnchecked(ctx.expression().accept(this), Expression.class); return getDelegate().resolveFunction(ctx.NOT().getText(), argument); } - @Nonnull @Override - public Expression visitLogicalExpression(@Nonnull RelationalParser.LogicalExpressionContext ctx) { + public Expression visitLogicalExpression(RelationalParser.LogicalExpressionContext ctx) { final var left = Assert.castUnchecked(ctx.expression(0).accept(this), Expression.class); final var right = Assert.castUnchecked(ctx.expression(1).accept(this), Expression.class); return getDelegate().resolveFunction(ctx.logicalOperator().getText(), left, right); } - @Nonnull @Override - public Expression visitPredicatedExpression(@Nonnull final RelationalParser.PredicatedExpressionContext ctx) { + public Expression visitPredicatedExpression(final RelationalParser.PredicatedExpressionContext ctx) { final var operand = Assert.castUnchecked(visit(ctx.expressionAtom()), Expression.class); final var predicate = ctx.predicate(); if (predicate == null) { @@ -602,9 +567,8 @@ public Expression visitPredicatedExpression(@Nonnull final RelationalParser.Pred return null; } - @Nonnull @Override - public Expression visitLimitClause(@Nonnull RelationalParser.LimitClauseContext ctx) { + public Expression visitLimitClause(RelationalParser.LimitClauseContext ctx) { // TODO (SQL query with OFFSET clause skipping wrong number of records with splitLongRecords=true in Relational) Assert.isNullUnchecked(ctx.offset, "OFFSET clause is not supported"); // the child must be literal not a ConstantObjectValue because the limit does not contribute anything @@ -616,17 +580,15 @@ public Expression visitLimitClause(@Nonnull RelationalParser.LimitClauseContext }); } - @Nonnull @Override - public Expression visitLimitClauseAtom(@Nonnull RelationalParser.LimitClauseAtomContext ctx) { + public Expression visitLimitClauseAtom(RelationalParser.LimitClauseAtomContext ctx) { return parseChild(ctx); } ///// Predicates /////// - @Nonnull @Override - public Expression visitExistsExpressionAtom(@Nonnull RelationalParser.ExistsExpressionAtomContext ctx) { + public Expression visitExistsExpressionAtom(RelationalParser.ExistsExpressionAtomContext ctx) { /* * (yhatem) this is an interesting visitation, as it requires three interactions: * - Firstly, LogicalOperator-visitor calls Expression-visitor to visit this predicate. @@ -643,8 +605,7 @@ public Expression visitExistsExpressionAtom(@Nonnull RelationalParser.ExistsExpr return Expression.ofUnnamed(underlyingValue); } - @Nonnull - private Expression visitIsExpression(@Nonnull Expression operand, @Nonnull RelationalParser.IsExpressionContext ctx) { + private Expression visitIsExpression(Expression operand, RelationalParser.IsExpressionContext ctx) { if (ctx.NULL_LITERAL() != null) { if (ctx.NOT() != null) { return getDelegate().resolveFunction("is not null", operand); @@ -668,8 +629,7 @@ private Expression visitIsExpression(@Nonnull Expression operand, @Nonnull Relat } } - @Nonnull - private Expression visitLikePredicate(@Nonnull Expression operand, @Nonnull RelationalParser.LikePredicateContext ctx) { + private Expression visitLikePredicate(Expression operand, RelationalParser.LikePredicateContext ctx) { final LiteralValue escapeValue; if (ctx.escape != null) { final var escapeChar = getDelegate().normalizeString(ctx.escape.getText()); @@ -687,8 +647,7 @@ private Expression visitLikePredicate(@Nonnull Expression operand, @Nonnull Rela return likeFunction; } - @Nonnull - private Expression visitInPredicate(@Nonnull Expression operand, @Nonnull RelationalParser.InPredicateContext ctx) { + private Expression visitInPredicate(Expression operand, RelationalParser.InPredicateContext ctx) { Assert.thatUnchecked(ctx.inList().queryExpressionBody() == null, ErrorCode.UNSUPPORTED_QUERY, "IN predicate does not support nested SELECT"); final var right = visitInList(ctx.inList()); @@ -699,9 +658,8 @@ private Expression visitInPredicate(@Nonnull Expression operand, @Nonnull Relati return in; } - @Nonnull @Override - public Expression visitInList(@Nonnull RelationalParser.InListContext ctx) { + public Expression visitInList(RelationalParser.InListContext ctx) { final Expression result; if (ctx.preparedStatementParameter() != null) { result = visitPreparedStatementParameter(ctx.preparedStatementParameter()); @@ -726,9 +684,8 @@ public Expression visitInList(@Nonnull RelationalParser.InListContext ctx) { return result; } - @Nonnull @Override - public Expression visitWhereExpr(@Nonnull RelationalParser.WhereExprContext ctx) { + public Expression visitWhereExpr(RelationalParser.WhereExprContext ctx) { final var expression = parseChild(ctx); // verify no window functions Assert.thatUnchecked(expression.getUnderlying().preOrderStream().noneMatch(v -> v instanceof WindowedValue), @@ -736,48 +693,43 @@ public Expression visitWhereExpr(@Nonnull RelationalParser.WhereExprContext ctx) return expression; } - @Nonnull @Override public Expression visitQualifyClause(final RelationalParser.QualifyClauseContext ctx) { return parseChild(ctx); } - @Nonnull @Override - public Expressions visitExpressions(@Nonnull RelationalParser.ExpressionsContext ctx) { + public Expressions visitExpressions(RelationalParser.ExpressionsContext ctx) { return Expressions.of(ctx.expression() .stream() .map(expression -> Assert.castUnchecked(expression.accept(this), Expression.class)) .collect(ImmutableList.toImmutableList())); } - @Nonnull @Override - public Expression visitBitExpressionAtom(@Nonnull RelationalParser.BitExpressionAtomContext ctx) { + public Expression visitBitExpressionAtom(RelationalParser.BitExpressionAtomContext ctx) { final var left = Assert.castUnchecked(ctx.left.accept(this), Expression.class); final var right = Assert.castUnchecked(ctx.right.accept(this), Expression.class); return getDelegate().resolveFunction(ctx.bitOperator().getText(), left, right); } - @Nonnull @Override - public Expression visitBinaryComparisonPredicate(@Nonnull RelationalParser.BinaryComparisonPredicateContext ctx) { + public Expression visitBinaryComparisonPredicate(RelationalParser.BinaryComparisonPredicateContext ctx) { final var left = Assert.castUnchecked(ctx.left.accept(this), Expression.class); final var right = Assert.castUnchecked(ctx.right.accept(this), Expression.class); return getDelegate().resolveFunction(ctx.comparisonOperator().getText(), left, right); } @Override - public Expression visitSubscriptExpression(@Nonnull RelationalParser.SubscriptExpressionContext ctx) { + public Expression visitSubscriptExpression(RelationalParser.SubscriptExpressionContext ctx) { final var index = Assert.castUnchecked(ctx.index.accept(this), Expression.class); final var base = Assert.castUnchecked(ctx.base.accept(this), Expression.class); return getDelegate().resolveFunction(ctx.LEFT_SQUARE_BRACKET().getText() .concat(ctx.RIGHT_SQUARE_BRACKET().getText()), index, base); } - @Nonnull - private Expression visitBetweenComparisonPredicate(@Nonnull Expression operand, - @Nonnull RelationalParser.BetweenComparisonPredicateContext ctx) { + private Expression visitBetweenComparisonPredicate(Expression operand, + RelationalParser.BetweenComparisonPredicateContext ctx) { final var left = Assert.castUnchecked(ctx.left.accept(this), Expression.class); final var right = Assert.castUnchecked(ctx.right.accept(this), Expression.class); if (ctx.NOT() == null) { @@ -791,17 +743,15 @@ private Expression visitBetweenComparisonPredicate(@Nonnull Expression operand, } } - @Nonnull @Override - public Expression visitMathExpressionAtom(@Nonnull RelationalParser.MathExpressionAtomContext ctx) { + public Expression visitMathExpressionAtom(RelationalParser.MathExpressionAtomContext ctx) { final var left = Assert.castUnchecked(ctx.left.accept(this), Expression.class); final var right = Assert.castUnchecked(ctx.right.accept(this), Expression.class); return getDelegate().resolveFunction(ctx.mathOperator().getText(), left, right); } - @Nonnull @Override - public Expression visitExpressionWithOptionalName(@Nonnull RelationalParser.ExpressionWithOptionalNameContext ctx) { + public Expression visitExpressionWithOptionalName(RelationalParser.ExpressionWithOptionalNameContext ctx) { final var expression = Assert.castUnchecked(ctx.expression().accept(this), Expression.class); if (ctx.AS() != null) { final var name = visitUid(ctx.uid()); @@ -812,15 +762,13 @@ public Expression visitExpressionWithOptionalName(@Nonnull RelationalParser.Expr /////// Literals and Constants ////// - @Nonnull @Override - public Expression visitDecimalLiteral(@Nonnull RelationalParser.DecimalLiteralContext ctx) { + public Expression visitDecimalLiteral(RelationalParser.DecimalLiteralContext ctx) { return resolveDecimal(ctx.getText(), ctx.getStart().getTokenIndex()); } - @Nonnull @Override - public Expression visitStringLiteral(@Nonnull RelationalParser.StringLiteralContext ctx) { + public Expression visitStringLiteral(RelationalParser.StringLiteralContext ctx) { Assert.isNullUnchecked(ctx.STRING_CHARSET_NAME(), ErrorCode.UNSUPPORTED_QUERY, "charset not is supported"); Assert.isNullUnchecked(ctx.START_NATIONAL_STRING_LITERAL(), ErrorCode.UNSUPPORTED_QUERY, "national string literal is not supported"); Assert.isNullUnchecked(ctx.COLLATE(), ErrorCode.UNSUPPORTED_QUERY, "collation is not supported"); @@ -830,9 +778,8 @@ public Expression visitStringLiteral(@Nonnull RelationalParser.StringLiteralCont return Expression.ofUnnamed(value); } - @Nonnull @Override - public Expression visitBooleanLiteral(@Nonnull RelationalParser.BooleanLiteralContext ctx) { + public Expression visitBooleanLiteral(RelationalParser.BooleanLiteralContext ctx) { final Value booleanValue; if (ctx.FALSE() != null) { booleanValue = getDelegate().getPlanGenerationContext().processQueryLiteral(Type.primitiveType(Type.TypeCode.BOOLEAN), Boolean.FALSE, @@ -845,9 +792,8 @@ public Expression visitBooleanLiteral(@Nonnull RelationalParser.BooleanLiteralCo return Expression.ofUnnamed(booleanValue); } - @Nonnull @Override - public Expression visitBytesLiteral(@Nonnull RelationalParser.BytesLiteralContext ctx) { + public Expression visitBytesLiteral(RelationalParser.BytesLiteralContext ctx) { final String literal; if (ctx.HEXADECIMAL_LITERAL() != null) { literal = ctx.HEXADECIMAL_LITERAL().getText(); @@ -860,67 +806,57 @@ public Expression visitBytesLiteral(@Nonnull RelationalParser.BytesLiteralContex return Expression.ofUnnamed(value); } - @Nonnull @Override - public Expression visitNullLiteral(@Nonnull RelationalParser.NullLiteralContext ctx) { + public Expression visitNullLiteral(RelationalParser.NullLiteralContext ctx) { return Expression.ofUnnamed(new NullValue(Type.nullType())); // do not strip nulls. } - @Nonnull @Override - public Expression visitStringConstant(@Nonnull RelationalParser.StringConstantContext ctx) { + public Expression visitStringConstant(RelationalParser.StringConstantContext ctx) { return parseChild(ctx); } - @Nonnull @Override - public Expression visitDecimalConstant(@Nonnull RelationalParser.DecimalConstantContext ctx) { + public Expression visitDecimalConstant(RelationalParser.DecimalConstantContext ctx) { return parseChild(ctx); } - @Nonnull @Override - public Expression visitNegativeDecimalConstant(@Nonnull RelationalParser.NegativeDecimalConstantContext ctx) { + public Expression visitNegativeDecimalConstant(RelationalParser.NegativeDecimalConstantContext ctx) { return resolveDecimal(ctx.getText(), ctx.getStart().getTokenIndex()); } - @Nonnull @Override - public Expression visitBytesConstant(@Nonnull RelationalParser.BytesConstantContext ctx) { + public Expression visitBytesConstant(RelationalParser.BytesConstantContext ctx) { return parseChild(ctx); } - @Nonnull @Override - public Expression visitBooleanConstant(@Nonnull RelationalParser.BooleanConstantContext ctx) { + public Expression visitBooleanConstant(RelationalParser.BooleanConstantContext ctx) { return parseChild(ctx); } - @Nonnull @Override - public Expression visitBitStringConstant(@Nonnull RelationalParser.BitStringConstantContext ctx) { + public Expression visitBitStringConstant(RelationalParser.BitStringConstantContext ctx) { Assert.failUnchecked(ErrorCode.UNSUPPORTED_QUERY, "bit strings not supported"); return null; } - @Nonnull @Override - public Expression visitNullConstant(@Nonnull RelationalParser.NullConstantContext ctx) { + public Expression visitNullConstant(RelationalParser.NullConstantContext ctx) { Assert.isNullUnchecked(ctx.NOT(), ErrorCode.UNSUPPORTED_QUERY, "not null is not supported"); return visitNullLiteral(ctx.nullLiteral()); } /////// Lists ////// - @Nonnull @Override - public CompatibleTypeEvolutionPredicate.FieldAccessTrieNode visitUidListWithNestingsInParens(@Nonnull final RelationalParser.UidListWithNestingsInParensContext ctx) { + public CompatibleTypeEvolutionPredicate.FieldAccessTrieNode visitUidListWithNestingsInParens(final RelationalParser.UidListWithNestingsInParensContext ctx) { return visitUidListWithNestings(ctx.uidListWithNestings()); } - @Nonnull @Override - public CompatibleTypeEvolutionPredicate.FieldAccessTrieNode visitUidListWithNestings(@Nonnull final RelationalParser.UidListWithNestingsContext ctx) { + public CompatibleTypeEvolutionPredicate.FieldAccessTrieNode visitUidListWithNestings(final RelationalParser.UidListWithNestingsContext ctx) { final var uidMap = Streams.mapWithIndex(ctx.uidWithNestings().stream(), (ctxWithNesting, index) -> { final var uid = visitUid(ctxWithNesting.uid()); @@ -938,23 +874,20 @@ public CompatibleTypeEvolutionPredicate.FieldAccessTrieNode visitUidListWithNest return CompatibleTypeEvolutionPredicate.FieldAccessTrieNode.of(Type.any(), uidMap); } - @Nonnull @Override - public Expression visitRecordConstructorForInsert(@Nonnull RelationalParser.RecordConstructorForInsertContext ctx) { + public Expression visitRecordConstructorForInsert(RelationalParser.RecordConstructorForInsertContext ctx) { final var expressions = parseRecordFieldsUnderReorderings(ctx.expressionWithOptionalName()); return Expression.ofUnnamed(RecordConstructorValue.ofColumns(expressions.underlyingAsColumns())); } - @Nonnull @Override - public Expression visitRecordConstructorForInlineTable(@Nonnull RelationalParser.RecordConstructorForInlineTableContext ctx) { + public Expression visitRecordConstructorForInlineTable(RelationalParser.RecordConstructorForInlineTableContext ctx) { final var expressions = parseRecordFieldsUnderReorderings(ctx.expressionWithOptionalName()); return Expression.ofUnnamed(RecordConstructorValue.ofColumns(expressions.underlyingAsColumns())); } - @Nonnull @Override - public Expression visitRecordConstructor(@Nonnull RelationalParser.RecordConstructorContext ctx) { + public Expression visitRecordConstructor(RelationalParser.RecordConstructorContext ctx) { if (ctx.uid() != null) { final var id = visitUid(ctx.uid()); if (ctx.STAR() == null) { @@ -993,9 +926,8 @@ public Expression visitRecordConstructor(@Nonnull RelationalParser.RecordConstru return Expression.ofUnnamed(resultValue); } - @Nonnull @Override - public Expression visitArrayConstructor(@Nonnull RelationalParser.ArrayConstructorContext ctx) { + public Expression visitArrayConstructor(RelationalParser.ArrayConstructorContext ctx) { final var maybeState = getStateMaybe(); final var targetTypeMaybe = maybeState.flatMap(LogicalPlanFragment.State::getTargetType); @@ -1019,9 +951,8 @@ public Expression visitArrayConstructor(@Nonnull RelationalParser.ArrayConstruct } } - @Nonnull - private Expressions parseRecordFields(@Nonnull List parserRuleContexts, - @Nullable List targetFields) { + private Expressions parseRecordFields(List parserRuleContexts, + @Nullable List targetFields) { Assert.thatUnchecked(targetFields == null || targetFields.size() == parserRuleContexts.size()); final var resultsBuilder = ImmutableList.builder(); for (int i = 0; i < parserRuleContexts.size(); i++) { @@ -1032,9 +963,8 @@ private Expressions parseRecordFields(@Nonnull List return Expressions.of(resultsBuilder.build()); } - @Nonnull - private Expression parseRecordField(@Nonnull ParserRuleContext parserRuleContext, - @Nullable Type.Record.Field targetField) { + private Expression parseRecordField(ParserRuleContext parserRuleContext, + @Nullable Field targetField) { final var fieldType = targetField == null ? null : targetField.getFieldType(); StringTrieNode reorderings = null; final var maybeState = getStateMaybe(); @@ -1076,10 +1006,9 @@ private Expression parseRecordField(@Nonnull ParserRuleContext parserRuleContext return coercedExpression; } - @Nonnull @SuppressWarnings("PMD.CompareObjectsWithEquals") - private static Expression coerceIfNecessary(@Nonnull Expression expression, - @Nonnull Type targetType) { + private static Expression coerceIfNecessary(Expression expression, + Type targetType) { final var value = expression.getUnderlying(); final var maybeCoercedValue = coerceValueIfNecessary(expression.getUnderlying(), targetType); if (value != maybeCoercedValue) { @@ -1089,8 +1018,7 @@ private static Expression coerceIfNecessary(@Nonnull Expression expression, } } - @Nonnull - private static Value coerceValueIfNecessary(@Nonnull Value value, @Nonnull Type targetType) { + private static Value coerceValueIfNecessary(Value value, Type targetType) { final var resultType = value.getResultType(); if (resultType.isUnresolved() || (resultType.isPrimitive() && PromoteValue.isPromotionNeeded(resultType, targetType))) { @@ -1104,8 +1032,7 @@ private static Value coerceValueIfNecessary(@Nonnull Value value, @Nonnull Type return value; } - @Nonnull - private Expressions parseRecordFieldsUnderReorderings(@Nonnull final List providedColumnContexts) { + private Expressions parseRecordFieldsUnderReorderings(final List providedColumnContexts) { final var maybeState = getStateMaybe(); if (maybeState.isEmpty() || maybeState.get().getTargetType().isEmpty()) { return parseRecordFields(providedColumnContexts, null); @@ -1150,16 +1077,14 @@ private Expressions parseRecordFieldsUnderReorderings(@Nonnull final List getStateMaybe() { return getDelegate().getCurrentPlanFragmentMaybe().flatMap(LogicalPlanFragment::getStateMaybe); } - @Nonnull - private Expression parseChild(@Nonnull ParserRuleContext context) { + private Expression parseChild(ParserRuleContext context) { return Assert.castUnchecked(visitChildren(context), Expression.class); } - @Nonnull - private Expression resolveDecimal(@Nonnull String decimalText, int tokenIndex) { + private Expression resolveDecimal(String decimalText, int tokenIndex) { final var literal = ParseHelpers.parseDecimal(decimalText); final var type = Type.fromObject(literal); final var value = getDelegate().getPlanGenerationContext().processQueryLiteral(type, literal, tokenIndex); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/IdentifierVisitor.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/IdentifierVisitor.java index c15b1038173..14b7d88afb8 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/IdentifierVisitor.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/IdentifierVisitor.java @@ -29,8 +29,6 @@ import com.apple.foundationdb.relational.util.ExcludeFromJacocoGeneratedReport; import com.google.common.collect.ImmutableList; - -import javax.annotation.Nonnull; import java.util.List; @API(API.Status.EXPERIMENTAL) @@ -40,20 +38,17 @@ private IdentifierVisitor(BaseVisitor baseVisitor) { super(baseVisitor); } - @Nonnull - public static IdentifierVisitor of(@Nonnull BaseVisitor baseVisitor) { + public static IdentifierVisitor of(BaseVisitor baseVisitor) { return new IdentifierVisitor(baseVisitor); } - @Nonnull @Override - public Identifier visitTableName(@Nonnull RelationalParser.TableNameContext tableNameContext) { + public Identifier visitTableName(RelationalParser.TableNameContext tableNameContext) { return visitFullId(tableNameContext.fullId()); } - @Nonnull @Override - public Identifier visitFullId(@Nonnull RelationalParser.FullIdContext fullIdContext) { + public Identifier visitFullId(RelationalParser.FullIdContext fullIdContext) { Assert.thatUnchecked(!fullIdContext.uid().isEmpty()); final ImmutableList.Builder qualifierBuilder = ImmutableList.builder(); for (int i = 0; i < fullIdContext.uid().size() - 1; i++) { @@ -65,14 +60,12 @@ public Identifier visitFullId(@Nonnull RelationalParser.FullIdContext fullIdCont } @Override - @Nonnull - public List visitFullIdList(@Nonnull RelationalParser.FullIdListContext fullIdListContext) { + public List visitFullIdList(RelationalParser.FullIdListContext fullIdListContext) { return fullIdListContext.fullId().stream().map(this::visitFullId).collect(ImmutableList.toImmutableList()); } - @Nonnull @Override - public Identifier visitUid(@Nonnull RelationalParser.UidContext uidContext) { + public Identifier visitUid(RelationalParser.UidContext uidContext) { if (uidContext.simpleId() != null) { return visitSimpleId(uidContext.simpleId()); } else { @@ -80,46 +73,41 @@ public Identifier visitUid(@Nonnull RelationalParser.UidContext uidContext) { } } - @Nonnull @Override - public List visitUidList(@Nonnull RelationalParser.UidListContext uidListContext) { + public List visitUidList(RelationalParser.UidListContext uidListContext) { return uidListContext.uid().stream() .map(this::visitUid) .collect(ImmutableList.toImmutableList()); } - @Nonnull @Override - public Identifier visitSimpleId(@Nonnull RelationalParser.SimpleIdContext simpleIdContext) { + public Identifier visitSimpleId(RelationalParser.SimpleIdContext simpleIdContext) { return Identifier.of(getDelegate().normalizeString(simpleIdContext.getText())); } - @Nonnull @Override // not supported yet @ExcludeFromJacocoGeneratedReport - public Identifier visitIndexColumnName(@Nonnull RelationalParser.IndexColumnNameContext ctx) { + public Identifier visitIndexColumnName(RelationalParser.IndexColumnNameContext ctx) { Assert.failUnchecked(ErrorCode.UNSUPPORTED_QUERY, "setting index column is not supported"); return null; } - @Nonnull @Override // not supported yet @ExcludeFromJacocoGeneratedReport - public Identifier visitCharsetName(@Nonnull RelationalParser.CharsetNameContext ctx) { + public Identifier visitCharsetName(RelationalParser.CharsetNameContext ctx) { Assert.failUnchecked(ErrorCode.UNSUPPORTED_QUERY, "setting charset is not supported"); return null; } - @Nonnull @Override // not supported yet @ExcludeFromJacocoGeneratedReport - public Identifier visitCollationName(@Nonnull RelationalParser.CollationNameContext ctx) { + public Identifier visitCollationName(RelationalParser.CollationNameContext ctx) { Assert.failUnchecked(ErrorCode.UNSUPPORTED_QUERY, "setting collation is not supported"); return null; } @Override - public Identifier visitTableFunctionName(@Nonnull final RelationalParser.TableFunctionNameContext ctx) { + public Identifier visitTableFunctionName(final RelationalParser.TableFunctionNameContext ctx) { return visitFullId(ctx.fullId()); } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/MetadataPlanVisitor.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/MetadataPlanVisitor.java index e107c222ef3..467a43d8351 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/MetadataPlanVisitor.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/MetadataPlanVisitor.java @@ -25,25 +25,21 @@ import com.apple.foundationdb.relational.recordlayer.query.CopyPlan; import com.apple.foundationdb.relational.recordlayer.query.QueryPlan; import com.apple.foundationdb.relational.recordlayer.query.SemanticAnalyzer; - -import javax.annotation.Nonnull; import java.net.URI; @API(API.Status.EXPERIMENTAL) public final class MetadataPlanVisitor extends DelegatingVisitor { - private MetadataPlanVisitor(@Nonnull BaseVisitor baseVisitor) { + private MetadataPlanVisitor(BaseVisitor baseVisitor) { super(baseVisitor); } - @Nonnull - public static MetadataPlanVisitor of(@Nonnull BaseVisitor baseVisitor) { + public static MetadataPlanVisitor of(BaseVisitor baseVisitor) { return new MetadataPlanVisitor(baseVisitor); } - @Nonnull @Override - public QueryPlan.MetadataQueryPlan visitShowDatabasesStatement(@Nonnull RelationalParser.ShowDatabasesStatementContext ctx) { + public QueryPlan.MetadataQueryPlan visitShowDatabasesStatement(RelationalParser.ShowDatabasesStatementContext ctx) { final var ddlFactory = getDelegate().getDdlQueryFactory(); if (ctx.path() != null) { final var databaseName = visitUid(ctx.path().uid()); @@ -53,16 +49,14 @@ public QueryPlan.MetadataQueryPlan visitShowDatabasesStatement(@Nonnull Relation return QueryPlan.MetadataQueryPlan.of(ddlFactory.getListDatabasesQueryAction(getDelegate().getDbUri())); } - @Nonnull @Override - public QueryPlan.MetadataQueryPlan visitShowSchemaTemplatesStatement(@Nonnull RelationalParser.ShowSchemaTemplatesStatementContext ctx) { + public QueryPlan.MetadataQueryPlan visitShowSchemaTemplatesStatement(RelationalParser.ShowSchemaTemplatesStatementContext ctx) { final var ddlFactory = getDelegate().getDdlQueryFactory(); return QueryPlan.MetadataQueryPlan.of(ddlFactory.getListSchemaTemplatesQueryAction()); } - @Nonnull @Override - public QueryPlan.MetadataQueryPlan visitSimpleDescribeSchemaStatement(@Nonnull RelationalParser.SimpleDescribeSchemaStatementContext ctx) { + public QueryPlan.MetadataQueryPlan visitSimpleDescribeSchemaStatement(RelationalParser.SimpleDescribeSchemaStatementContext ctx) { final var ddlFactory = getDelegate().getDdlQueryFactory(); final var schemaId = visitUid(ctx.schemaId().path().uid()); final var dbAndSchema = SemanticAnalyzer.parseSchemaIdentifier(schemaId); @@ -71,25 +65,22 @@ public QueryPlan.MetadataQueryPlan visitSimpleDescribeSchemaStatement(@Nonnull R return QueryPlan.MetadataQueryPlan.of(ddlFactory.getDescribeSchemaQueryAction(database, schema)); } - @Nonnull @Override - public QueryPlan.MetadataQueryPlan visitSimpleDescribeSchemaTemplateStatement(@Nonnull RelationalParser.SimpleDescribeSchemaTemplateStatementContext ctx) { + public QueryPlan.MetadataQueryPlan visitSimpleDescribeSchemaTemplateStatement(RelationalParser.SimpleDescribeSchemaTemplateStatementContext ctx) { final var ddlFactory = getDelegate().getDdlQueryFactory(); final var schemaTemplateId = visitUid(ctx.uid()); return QueryPlan.MetadataQueryPlan.of(ddlFactory.getDescribeSchemaTemplateQueryAction(schemaTemplateId.getName())); } - @Nonnull @Override - public QueryPlan visitCopyExportStatement(@Nonnull RelationalParser.CopyExportStatementContext ctx) { + public QueryPlan visitCopyExportStatement(RelationalParser.CopyExportStatementContext ctx) { final var pathId = visitUid(ctx.path().uid()); final boolean incrementIncarnation = ctx.incarnationOption().INCREMENT() != null; return CopyPlan.getCopyExportAction(pathId.getName(), getDelegate().getPlanGenerationContext(), incrementIncarnation); } - @Nonnull @Override - public QueryPlan visitCopyImportStatement(@Nonnull RelationalParser.CopyImportStatementContext ctx) { + public QueryPlan visitCopyImportStatement(RelationalParser.CopyImportStatementContext ctx) { final var pathId = visitUid(ctx.path().uid()); // We must visit the parameter to ensure that it ends up in the Literals in the query execution context visitPreparedStatementParameter(ctx.preparedStatementParameter()); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/QueryVisitor.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/QueryVisitor.java index e856bdaa223..573b40e0e64 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/QueryVisitor.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/QueryVisitor.java @@ -65,9 +65,7 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Streams; import org.antlr.v4.runtime.ParserRuleContext; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.List; import java.util.Optional; import java.util.Set; @@ -89,18 +87,16 @@ @API(API.Status.EXPERIMENTAL) public final class QueryVisitor extends DelegatingVisitor { - private QueryVisitor(@Nonnull BaseVisitor baseVisitor) { + private QueryVisitor(BaseVisitor baseVisitor) { super(baseVisitor); } - @Nonnull - public static QueryVisitor of(@Nonnull BaseVisitor baseVisitor) { + public static QueryVisitor of(BaseVisitor baseVisitor) { return new QueryVisitor(baseVisitor); } - @Nonnull @Override - public QueryPlan.LogicalQueryPlan visitSelectStatement(@Nonnull RelationalParser.SelectStatementContext ctx) { + public QueryPlan.LogicalQueryPlan visitSelectStatement(RelationalParser.SelectStatementContext ctx) { final var logicalOperator = parseChild(ctx); // Capture semantic type structure as StructType with field names final var semanticStructType = logicalOperator.getOutput().getStructType(); @@ -108,9 +104,8 @@ public QueryPlan.LogicalQueryPlan visitSelectStatement(@Nonnull RelationalParser getDelegate().getPlanGenerationContext(), getDelegate().getPlanGenerationContext().getQuery(), semanticStructType); } - @Nonnull @Override - public QueryPlan.LogicalQueryPlan visitDmlStatement(@Nonnull RelationalParser.DmlStatementContext ctx) { + public QueryPlan.LogicalQueryPlan visitDmlStatement(RelationalParser.DmlStatementContext ctx) { final var logicalOperator = parseChild(ctx); // Capture semantic type structure as StructType with field names final var semanticStructType = logicalOperator.getOutput().getStructType(); @@ -118,9 +113,8 @@ public QueryPlan.LogicalQueryPlan visitDmlStatement(@Nonnull RelationalParser.Dm getDelegate().getPlanGenerationContext(), getDelegate().getPlanGenerationContext().getQuery(), semanticStructType); } - @Nonnull @Override - public LogicalOperator visitQuery(@Nonnull RelationalParser.QueryContext ctx) { + public LogicalOperator visitQuery(RelationalParser.QueryContext ctx) { if (ctx.ctes() != null) { getDelegate().pushPlanFragment(); visitCtes(ctx.ctes()); @@ -133,7 +127,7 @@ public LogicalOperator visitQuery(@Nonnull RelationalParser.QueryContext ctx) { @Nullable @Override - public Void visitCtes(@Nonnull RelationalParser.CtesContext ctx) { + public Void visitCtes(RelationalParser.CtesContext ctx) { final var currentPlanFragment = getDelegate().getCurrentPlanFragment(); if (ctx.RECURSIVE() != null) { final RecursiveUnionExpression.TraversalStrategy traversalStrategy; @@ -166,9 +160,8 @@ public Void visitCtes(@Nonnull RelationalParser.CtesContext ctx) { } @SuppressWarnings("UnstableApiUsage") - @Nonnull @Override - public LogicalOperator visitNamedQuery(@Nonnull RelationalParser.NamedQueryContext ctx) { + public LogicalOperator visitNamedQuery(RelationalParser.NamedQueryContext ctx) { final var queryName = visitFullId(ctx.name); var logicalOperator = visitQuery(ctx.query()); if (ctx.columnAliases != null) { @@ -183,9 +176,8 @@ public LogicalOperator visitNamedQuery(@Nonnull RelationalParser.NamedQueryConte } @SuppressWarnings("UnstableApiUsage") - @Nonnull - public LogicalOperator handleRecursiveNamedQuery(@Nonnull final RelationalParser.NamedQueryContext recursiveQueryContext, - @Nonnull final RecursiveUnionExpression.TraversalStrategy traversalStrategy) { + public LogicalOperator handleRecursiveNamedQuery(final RelationalParser.NamedQueryContext recursiveQueryContext, + final RecursiveUnionExpression.TraversalStrategy traversalStrategy) { final var queryName = visitFullId(recursiveQueryContext.name); final Optional recursiveQueryType; final var memoized = MemoizedFunction.>memoize( @@ -240,9 +232,8 @@ public LogicalOperator handleRecursiveNamedQuery(@Nonnull final RelationalParser * Combines a seed expression with a list of additional expressions using {@code AND}. Returns the seed unchanged * if {@code expressions} is empty, or an empty optional if both the seed and the list are empty. */ - @Nonnull private Optional conjoinExpressions(@Nullable Expression seed, - @Nonnull final List expressions) { + final List expressions) { for (final Expression expression : expressions) { if (seed != null) { seed = getDelegate().resolveFunction("and", seed, expression); @@ -253,9 +244,8 @@ private Optional conjoinExpressions(@Nullable Expression seed, return Optional.ofNullable(seed); } - @Nonnull @Override - public LogicalOperator visitSimpleTable(@Nonnull RelationalParser.SimpleTableContext simpleTableContext) { + public LogicalOperator visitSimpleTable(RelationalParser.SimpleTableContext simpleTableContext) { getDelegate().pushPlanFragment(); if (simpleTableContext.fromClause() != null) { simpleTableContext.fromClause().accept(this); @@ -342,21 +332,18 @@ public LogicalOperator visitSimpleTable(@Nonnull RelationalParser.SimpleTableCon return result; } - @Nonnull @Override - public LogicalOperator visitParenthesisQuery(@Nonnull RelationalParser.ParenthesisQueryContext ctx) { + public LogicalOperator visitParenthesisQuery(RelationalParser.ParenthesisQueryContext ctx) { return visitQuery(ctx.query()); } - @Nonnull @Override - public LogicalOperator visitQueryTermDefault(@Nonnull RelationalParser.QueryTermDefaultContext queryTermDefaultContext) { + public LogicalOperator visitQueryTermDefault(RelationalParser.QueryTermDefaultContext queryTermDefaultContext) { return parseChild(queryTermDefaultContext); } - @Nonnull @Override - public LogicalOperator visitSetQuery(@Nonnull RelationalParser.SetQueryContext setQueryContext) { + public LogicalOperator visitSetQuery(RelationalParser.SetQueryContext setQueryContext) { Assert.thatUnchecked(setQueryContext.quantifier != null && setQueryContext.quantifier.getType() == ALL, ErrorCode.UNSUPPORTED_QUERY, "only UNION ALL is supported"); final var unionLegs = ImmutableList.of(Assert.castUnchecked(visit(setQueryContext.left), LogicalOperator.class), @@ -367,14 +354,14 @@ public LogicalOperator visitSetQuery(@Nonnull RelationalParser.SetQueryContext s @Nullable @Override - public Void visitFromClause(@Nonnull RelationalParser.FromClauseContext fromClauseContext) { + public Void visitFromClause(RelationalParser.FromClauseContext fromClauseContext) { fromClauseContext.tableSources().accept(this); return null; } @Nullable @Override - public Void visitTableSources(@Nonnull RelationalParser.TableSourcesContext ctx) { + public Void visitTableSources(RelationalParser.TableSourcesContext ctx) { for (final var tableSource : ctx.tableSource()) { tableSource.accept(this); } @@ -383,7 +370,7 @@ public Void visitTableSources(@Nonnull RelationalParser.TableSourcesContext ctx) @Nullable @Override - public Void visitTableSourceBase(@Nonnull RelationalParser.TableSourceBaseContext ctx) { + public Void visitTableSourceBase(RelationalParser.TableSourceBaseContext ctx) { getDelegate().getCurrentPlanFragment().addOperator(Assert.castUnchecked(ctx.tableSourceItem().accept(this), LogicalOperator.class)); for (final var joinPart : ctx.joinPart()) { joinPart.accept(this); @@ -403,11 +390,10 @@ public Void visitTableSourceBase(@Nonnull RelationalParser.TableSourceBaseContex * * @return a pair of the (possibly updated) right table source and the combined equality expression */ - @Nonnull private NonnullPair resolveJoinUsingClause( - @Nonnull final LogicalOperators leftOperators, - @Nonnull LogicalOperator rightTableSource, - @Nonnull final RelationalParser.UidListContext uidList) { + final LogicalOperators leftOperators, + LogicalOperator rightTableSource, + final RelationalParser.UidListContext uidList) { Assert.thatUnchecked(!uidList.isEmpty()); final BaseVisitor delegate = getDelegate(); final SemanticAnalyzer analyzer = delegate.getSemanticAnalyzer(); @@ -446,7 +432,7 @@ private NonnullPair resolveJoinUsingClause( */ @Nullable @Override - public Void visitInnerJoin(@Nonnull RelationalParser.InnerJoinContext ctx) { + public Void visitInnerJoin(RelationalParser.InnerJoinContext ctx) { LogicalOperator rightTableSource = Assert.castUnchecked(ctx.tableSourceItem().accept(this), LogicalOperator.class); final LogicalPlanFragment fragment = getDelegate().getCurrentPlanFragment(); @@ -484,8 +470,7 @@ private enum JoinType { /** * Extracts the {@link JoinType} from an {@code OuterJoinContext}. */ - @Nonnull - private static JoinType getJoinType(@Nonnull final RelationalParser.OuterJoinContext ctx) { + private static JoinType getJoinType(final RelationalParser.OuterJoinContext ctx) { if (ctx.LEFT() != null) { return JoinType.LEFT; } else if (ctx.RIGHT() != null) { @@ -513,7 +498,7 @@ private static JoinType getJoinType(@Nonnull final RelationalParser.OuterJoinCon */ @Nullable @Override - public Void visitOuterJoin(@Nonnull RelationalParser.OuterJoinContext ctx) { + public Void visitOuterJoin(RelationalParser.OuterJoinContext ctx) { final JoinType joinType = getJoinType(ctx); Assert.thatUnchecked(joinType != JoinType.FULL, ErrorCode.UNSUPPORTED_QUERY, "FULL OUTER JOIN is not currently supported"); @@ -559,7 +544,7 @@ public Void visitOuterJoin(@Nonnull RelationalParser.OuterJoinContext ctx) { * original operators, preserving qualified names for subsequent column resolution. Any pending inner join * predicates are absorbed into the new {@code SelectExpression}. */ - private void collapseLeftSideOperators(@Nonnull final LogicalPlanFragment fragment) { + private void collapseLeftSideOperators(final LogicalPlanFragment fragment) { final LogicalOperators ops = fragment.getLogicalOperators(); final List quns = ops.getQuantifiers(); final Expressions exprs = ops.getExpressions(); @@ -611,9 +596,9 @@ private void collapseLeftSideOperators(@Nonnull final LogicalPlanFragment fragme * @param rightTableSource the SQL-right table operator, already present in the fragment * @param onExpression the resolved ON-clause expression */ - private void wrapOperandsForOuterJoin(@Nonnull final JoinType joinType, - @Nonnull final LogicalOperator rightTableSource, - @Nonnull final Expression onExpression) { + private void wrapOperandsForOuterJoin(final JoinType joinType, + final LogicalOperator rightTableSource, + final Expression onExpression) { final LogicalPlanFragment fragment = getDelegate().getCurrentPlanFragment(); final LogicalOperators operators = fragment.getLogicalOperators(); final List quantifiers = operators.getQuantifiers(); @@ -678,9 +663,8 @@ private void wrapOperandsForOuterJoin(@Nonnull final JoinType joinType, fragment.setOperator(LogicalOperator.newOperatorWithPreservedExpressionNames(rewiredOutput, outerJoinQun)); } - @Nonnull @Override - public LogicalOperator visitAtomTableItem(@Nonnull RelationalParser.AtomTableItemContext atomTableItemContext) { + public LogicalOperator visitAtomTableItem(RelationalParser.AtomTableItemContext atomTableItemContext) { final var tableIdentifier = Assert.castUnchecked(atomTableItemContext.tableName().accept(this), Identifier.class); final var tableAlias = Optional.of(atomTableItemContext.alias == null ? visitTableName(atomTableItemContext.tableName()) : visitUid(atomTableItemContext.alias)); @@ -693,17 +677,15 @@ public LogicalOperator visitAtomTableItem(@Nonnull RelationalParser.AtomTableIte getDelegate().getCurrentPlanFragment(), getDelegate().getLogicalOperatorCatalog()); } - @Nonnull @Override - public LogicalOperator visitSubqueryTableItem(@Nonnull RelationalParser.SubqueryTableItemContext subqueryTableItemContext) { + public LogicalOperator visitSubqueryTableItem(RelationalParser.SubqueryTableItemContext subqueryTableItemContext) { final var alias = Assert.castUnchecked(subqueryTableItemContext.alias.accept(this), Identifier.class); final var selectOperator = visitQuery(subqueryTableItemContext.query()); return selectOperator.withName(alias); } - @Nonnull @Override - public LogicalOperator visitInlineTableItem(@Nonnull RelationalParser.InlineTableItemContext inlineTableItemContext) { + public LogicalOperator visitInlineTableItem(RelationalParser.InlineTableItemContext inlineTableItemContext) { NonnullPair typeMaybe = null; if (inlineTableItemContext.inlineTableDefinition() != null) { typeMaybe = visitInlineTableDefinition(inlineTableItemContext.inlineTableDefinition()); @@ -737,16 +719,15 @@ public LogicalOperator visitInlineTableItem(@Nonnull RelationalParser.InlineTabl } @Override - public LogicalOperator visitTableValuedFunction(@Nonnull RelationalParser.TableValuedFunctionContext tableValuedFunctionContext) { + public LogicalOperator visitTableValuedFunction(RelationalParser.TableValuedFunctionContext tableValuedFunctionContext) { final var logicalOperator = visitTableFunction(tableValuedFunctionContext.tableFunction()); final var aliasMaybe = Optional.ofNullable(tableValuedFunctionContext.uid() == null ? null : visitUid(tableValuedFunctionContext.uid())); return aliasMaybe.map(logicalOperator::withName).orElse(logicalOperator); } - @Nonnull @Override - public Set visitIndexHint(@Nonnull RelationalParser.IndexHintContext indexHintContext) { + public Set visitIndexHint(RelationalParser.IndexHintContext indexHintContext) { // currently only support USE INDEX '(' uidList ')' syntax Assert.isNullUnchecked(indexHintContext.IGNORE(), "index hint 'ignore' semantics not supported"); Assert.isNullUnchecked(indexHintContext.FORCE(), "index hint 'force' semantics not supported"); @@ -756,9 +737,8 @@ public Set visitIndexHint(@Nonnull RelationalParser.IndexHintContext ind return indexHintContext.uidList().uid().stream().map(this::visitUid).map(Identifier::getName).collect(ImmutableSet.toImmutableSet()); } - @Nonnull @Override - public LogicalOperator visitInsertStatement(@Nonnull RelationalParser.InsertStatementContext ctx) { + public LogicalOperator visitInsertStatement(RelationalParser.InsertStatementContext ctx) { final var table = visitTableName(ctx.tableName()); final var tableType = getDelegate().getSemanticAnalyzer().getTable(table); final var targetType = Assert.castUnchecked(tableType, RecordLayerTable.class).getType(); @@ -786,8 +766,7 @@ public LogicalOperator visitInsertStatement(@Nonnull RelationalParser.InsertStat return resultingInsert; } - @Nonnull - private static StringTrieNode toString(@Nonnull CompatibleTypeEvolutionPredicate.FieldAccessTrieNode fieldAccessTrieNode) { + private static StringTrieNode toString(CompatibleTypeEvolutionPredicate.FieldAccessTrieNode fieldAccessTrieNode) { if (fieldAccessTrieNode.getChildrenMap() == null) { return StringTrieNode.leafNode(); } @@ -795,15 +774,13 @@ private static StringTrieNode toString(@Nonnull CompatibleTypeEvolutionPredicate return new StringTrieNode(map); } - @Nonnull @Override - public LogicalOperator visitInsertStatementValueSelect(@Nonnull RelationalParser.InsertStatementValueSelectContext ctx) { + public LogicalOperator visitInsertStatementValueSelect(RelationalParser.InsertStatementValueSelectContext ctx) { return Assert.castUnchecked(ctx.queryExpressionBody().accept(this), LogicalOperator.class); } - @Nonnull @Override - public LogicalOperator visitInsertStatementValueValues(@Nonnull RelationalParser.InsertStatementValueValuesContext ctx) { + public LogicalOperator visitInsertStatementValueValues(RelationalParser.InsertStatementValueValuesContext ctx) { final ImmutableList.Builder insertTuples = ImmutableList.builder(); for (final var tupleContext : ctx.recordConstructorForInsert()) { insertTuples.add(visitRecordConstructorForInsert(tupleContext)); @@ -815,9 +792,8 @@ public LogicalOperator visitInsertStatementValueValues(@Nonnull RelationalParser return LogicalOperator.newUnnamedOperator(Expressions.ofSingle(arrayOfTuples), resultingQuantifier); } - @Nonnull @Override - public LogicalOperator visitUpdateStatement(@Nonnull RelationalParser.UpdateStatementContext ctx) { + public LogicalOperator visitUpdateStatement(RelationalParser.UpdateStatementContext ctx) { final Identifier tableId = visitFullId(ctx.tableName().fullId()); final SemanticAnalyzer semanticAnalyzer = getDelegate().getSemanticAnalyzer(); final RecordLayerTable table = Assert.castUnchecked(semanticAnalyzer.getTable(tableId), RecordLayerTable.class); @@ -868,9 +844,8 @@ public LogicalOperator visitUpdateStatement(@Nonnull RelationalParser.UpdateStat return result; } - @Nonnull @Override - public LogicalOperator visitDeleteStatement(@Nonnull RelationalParser.DeleteStatementContext ctx) { + public LogicalOperator visitDeleteStatement(RelationalParser.DeleteStatementContext ctx) { Assert.thatUnchecked(ctx.limitClause() == null, "limit is not supported"); final Identifier tableId = visitFullId(ctx.tableName().fullId()); final SemanticAnalyzer semanticAnalyzer = getDelegate().getSemanticAnalyzer(); @@ -903,42 +878,36 @@ public LogicalOperator visitDeleteStatement(@Nonnull RelationalParser.DeleteStat return result; } - @Nonnull @Override - public Object visitExecuteContinuationStatement(@Nonnull RelationalParser.ExecuteContinuationStatementContext ctx) { + public Object visitExecuteContinuationStatement(RelationalParser.ExecuteContinuationStatementContext ctx) { // TODO (Rethink how execute continuation works) throw Assert.failUnchecked("execute package should not be handled here"); } - @Nonnull @Override - public QueryPlan.LogicalQueryPlan visitFullDescribeStatement(@Nonnull RelationalParser.FullDescribeStatementContext ctx) { + public QueryPlan.LogicalQueryPlan visitFullDescribeStatement(RelationalParser.FullDescribeStatementContext ctx) { throw new RelationalException("Explain/Describe statement should not appear at the parser level", ErrorCode.INTERNAL_ERROR).toUncheckedWrappedException(); } - @Nonnull @Override - public QueryPlan.LogicalQueryPlan visitDescribeStatements(@Nonnull RelationalParser.DescribeStatementsContext ctx) { + public QueryPlan.LogicalQueryPlan visitDescribeStatements(RelationalParser.DescribeStatementsContext ctx) { final var logicalOperator = parseChild(ctx); final var semanticStructType = logicalOperator.getOutput().getStructType(); return QueryPlan.LogicalQueryPlan.of(logicalOperator.getQuantifier().getRangesOver().get(), getDelegate().getPlanGenerationContext(), getDelegate().getPlanGenerationContext().getQuery(), semanticStructType); } - @Nonnull @Override - public Object visitDescribeConnection(@Nonnull RelationalParser.DescribeConnectionContext ctx) { + public Object visitDescribeConnection(RelationalParser.DescribeConnectionContext ctx) { throw Assert.failUnchecked(ErrorCode.UNSUPPORTED_QUERY, "query is not supported"); } - @Nonnull private LogicalOperator parseChild(ParserRuleContext context) { return Assert.castUnchecked(visitChildren(context), LogicalOperator.class); } - @Nonnull - public List visitOrderByClauseForSelect(@Nonnull RelationalParser.OrderByClauseContext orderByClauseContext, - @Nonnull Expressions visibleSelectAliases) { + public List visitOrderByClauseForSelect(RelationalParser.OrderByClauseContext orderByClauseContext, + Expressions visibleSelectAliases) { final var validSelectAliases = Expressions.of(visibleSelectAliases.stream() .filter(expr -> expr.getName().isPresent() && !expr.getName().get().isQualified()) .collect(ImmutableList.toImmutableList())); @@ -967,15 +936,14 @@ public List visitOrderByClauseForSelect(@Nonnull RelationalPa return orderBys; } - private boolean hasAggregations(@Nonnull RelationalParser.SelectElementsContext selectElementsContext) { + private boolean hasAggregations(RelationalParser.SelectElementsContext selectElementsContext) { return getDelegate().getPlanGenerationContext().withDisabledLiteralProcessing( () -> Streams.stream(visitSelectElements(selectElementsContext)) .anyMatch(expression -> !Iterables.isEmpty(Expression.Utils.filterUnderlyingAggregates(expression))) ); } - @Nonnull - private static Optional isAliasMaybe(@Nonnull RelationalParser.OrderByExpressionContext orderByExpressionContext) { + private static Optional isAliasMaybe(RelationalParser.OrderByExpressionContext orderByExpressionContext) { if (!(orderByExpressionContext.expression() instanceof RelationalParser.PredicatedExpressionContext)) { return Optional.empty(); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/TypedVisitor.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/TypedVisitor.java index 5bce3a8cc61..63941d911ca 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/TypedVisitor.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/TypedVisitor.java @@ -38,9 +38,7 @@ import com.apple.foundationdb.relational.recordlayer.query.ProceduralPlan; import com.apple.foundationdb.relational.recordlayer.query.QueryPlan; import com.apple.foundationdb.relational.recordlayer.query.functions.CompiledSqlFunction; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.List; import java.util.Set; @@ -55,137 +53,105 @@ */ public interface TypedVisitor extends RelationalParserVisitor { - @Nonnull @Override - Object visitRoot(@Nonnull RelationalParser.RootContext ctx); + Object visitRoot(RelationalParser.RootContext ctx); - @Nonnull @Override - Object visitStatements(@Nonnull RelationalParser.StatementsContext ctx); + Object visitStatements(RelationalParser.StatementsContext ctx); @Nullable @Override - Object visitStatement(@Nonnull RelationalParser.StatementContext ctx); + Object visitStatement(RelationalParser.StatementContext ctx); - @Nonnull @Override - QueryPlan.LogicalQueryPlan visitDmlStatement(@Nonnull RelationalParser.DmlStatementContext ctx); + QueryPlan.LogicalQueryPlan visitDmlStatement(RelationalParser.DmlStatementContext ctx); - @Nonnull @Override Object visitDdlStatement(RelationalParser.DdlStatementContext ctx); - @Nonnull @Override - Object visitTransactionStatement(@Nonnull RelationalParser.TransactionStatementContext ctx); + Object visitTransactionStatement(RelationalParser.TransactionStatementContext ctx); - @Nonnull @Override - Object visitPreparedStatement(@Nonnull RelationalParser.PreparedStatementContext ctx); + Object visitPreparedStatement(RelationalParser.PreparedStatementContext ctx); - @Nonnull @Override - Object visitAdministrationStatement(@Nonnull RelationalParser.AdministrationStatementContext ctx); + Object visitAdministrationStatement(RelationalParser.AdministrationStatementContext ctx); - @Nonnull @Override - Object visitUtilityStatement(@Nonnull RelationalParser.UtilityStatementContext ctx); + Object visitUtilityStatement(RelationalParser.UtilityStatementContext ctx); - @Nonnull @Override - Object visitTemplateClause(@Nonnull RelationalParser.TemplateClauseContext ctx); + Object visitTemplateClause(RelationalParser.TemplateClauseContext ctx); - @Nonnull @Override - ProceduralPlan visitCreateSchemaStatement(@Nonnull RelationalParser.CreateSchemaStatementContext ctx); + ProceduralPlan visitCreateSchemaStatement(RelationalParser.CreateSchemaStatementContext ctx); - @Nonnull @Override - ProceduralPlan visitCreateSchemaTemplateStatement(@Nonnull RelationalParser.CreateSchemaTemplateStatementContext ctx); + ProceduralPlan visitCreateSchemaTemplateStatement(RelationalParser.CreateSchemaTemplateStatementContext ctx); - @Nonnull @Override - ProceduralPlan visitCreateDatabaseStatement(@Nonnull RelationalParser.CreateDatabaseStatementContext ctx); + ProceduralPlan visitCreateDatabaseStatement(RelationalParser.CreateDatabaseStatementContext ctx); - @Nonnull @Override - Object visitOptionsClause(@Nonnull RelationalParser.OptionsClauseContext ctx); + Object visitOptionsClause(RelationalParser.OptionsClauseContext ctx); - @Nonnull @Override - Object visitOption(@Nonnull RelationalParser.OptionContext ctx); + Object visitOption(RelationalParser.OptionContext ctx); - @Nonnull @Override - ProceduralPlan visitDropDatabaseStatement(@Nonnull RelationalParser.DropDatabaseStatementContext ctx); + ProceduralPlan visitDropDatabaseStatement(RelationalParser.DropDatabaseStatementContext ctx); - @Nonnull @Override - ProceduralPlan visitDropSchemaTemplateStatement(@Nonnull RelationalParser.DropSchemaTemplateStatementContext ctx); + ProceduralPlan visitDropSchemaTemplateStatement(RelationalParser.DropSchemaTemplateStatementContext ctx); - @Nonnull @Override - ProceduralPlan visitDropSchemaStatement(@Nonnull RelationalParser.DropSchemaStatementContext ctx); + ProceduralPlan visitDropSchemaStatement(RelationalParser.DropSchemaStatementContext ctx); - @Nonnull @Override - RecordLayerTable visitStructDefinition(@Nonnull RelationalParser.StructDefinitionContext ctx); + RecordLayerTable visitStructDefinition(RelationalParser.StructDefinitionContext ctx); - @Nonnull @Override - RecordLayerTable visitTableDefinition(@Nonnull RelationalParser.TableDefinitionContext ctx); + RecordLayerTable visitTableDefinition(RelationalParser.TableDefinitionContext ctx); - @Nonnull @Override - Object visitColumnDefinition(@Nonnull RelationalParser.ColumnDefinitionContext ctx); + Object visitColumnDefinition(RelationalParser.ColumnDefinitionContext ctx); - @Nonnull @Override - DataType visitFunctionColumnType(@Nonnull RelationalParser.FunctionColumnTypeContext ctx); + DataType visitFunctionColumnType(RelationalParser.FunctionColumnTypeContext ctx); - @Nonnull @Override - Object visitColumnType(@Nonnull RelationalParser.ColumnTypeContext ctx); + Object visitColumnType(RelationalParser.ColumnTypeContext ctx); - @Nonnull @Override - Boolean visitNullColumnConstraint(@Nonnull RelationalParser.NullColumnConstraintContext ctx); + Boolean visitNullColumnConstraint(RelationalParser.NullColumnConstraintContext ctx); - @Nonnull @Override - Object visitPrimaryKeyDefinition(@Nonnull RelationalParser.PrimaryKeyDefinitionContext ctx); + Object visitPrimaryKeyDefinition(RelationalParser.PrimaryKeyDefinitionContext ctx); @Override - @Nonnull List visitFullIdList(RelationalParser.FullIdListContext ctx); - @Nonnull @Override - DataType.Named visitEnumDefinition(@Nonnull RelationalParser.EnumDefinitionContext ctx); + DataType.Named visitEnumDefinition(RelationalParser.EnumDefinitionContext ctx); - @Nonnull @Override - RecordLayerIndex visitIndexAsSelectDefinition(@Nonnull RelationalParser.IndexAsSelectDefinitionContext ctx); + RecordLayerIndex visitIndexAsSelectDefinition(RelationalParser.IndexAsSelectDefinitionContext ctx); - @Nonnull @Override - RecordLayerIndex visitIndexOnSourceDefinition(@Nonnull RelationalParser.IndexOnSourceDefinitionContext ctx); + RecordLayerIndex visitIndexOnSourceDefinition(RelationalParser.IndexOnSourceDefinitionContext ctx); - @Nonnull @Override RecordLayerIndex visitVectorIndexDefinition(RelationalParser.VectorIndexDefinitionContext ctx); - @Nonnull @Override - Object visitIndexColumnList(@Nonnull RelationalParser.IndexColumnListContext ctx); + Object visitIndexColumnList(RelationalParser.IndexColumnListContext ctx); - @Nonnull @Override - Object visitIndexColumnSpec(@Nonnull RelationalParser.IndexColumnSpecContext ctx); + Object visitIndexColumnSpec(RelationalParser.IndexColumnSpecContext ctx); - @Nonnull @Override - Object visitIncludeClause(@Nonnull RelationalParser.IncludeClauseContext ctx); + Object visitIncludeClause(RelationalParser.IncludeClauseContext ctx); @Override Object visitIndexAttributes(RelationalParser.IndexAttributesContext ctx); @@ -226,52 +192,42 @@ public interface TypedVisitor extends RelationalParserVisitor { @Override DataType visitReturnsType(RelationalParser.ReturnsTypeContext ctx); - @Nonnull @Override - Object visitCharSet(@Nonnull RelationalParser.CharSetContext ctx); + Object visitCharSet(RelationalParser.CharSetContext ctx); - @Nonnull @Override - Object visitIntervalType(@Nonnull RelationalParser.IntervalTypeContext ctx); + Object visitIntervalType(RelationalParser.IntervalTypeContext ctx); - @Nonnull @Override - Object visitSchemaId(@Nonnull RelationalParser.SchemaIdContext ctx); + Object visitSchemaId(RelationalParser.SchemaIdContext ctx); - @Nonnull @Override - Object visitPath(@Nonnull RelationalParser.PathContext ctx); + Object visitPath(RelationalParser.PathContext ctx); - @Nonnull @Override - Object visitSchemaTemplateId(@Nonnull RelationalParser.SchemaTemplateIdContext ctx); + Object visitSchemaTemplateId(RelationalParser.SchemaTemplateIdContext ctx); - @Nonnull @Override - LogicalOperator visitDeleteStatement(@Nonnull RelationalParser.DeleteStatementContext ctx); + LogicalOperator visitDeleteStatement(RelationalParser.DeleteStatementContext ctx); - @Nonnull @Override - LogicalOperator visitInsertStatement(@Nonnull RelationalParser.InsertStatementContext ctx); + LogicalOperator visitInsertStatement(RelationalParser.InsertStatementContext ctx); - @Nonnull @Override QueryPlan.LogicalQueryPlan visitSelectStatement(RelationalParser.SelectStatementContext ctx); - @Nonnull @Override - LogicalOperator visitQuery(@Nonnull RelationalParser.QueryContext ctx); + LogicalOperator visitQuery(RelationalParser.QueryContext ctx); @Nullable @Override Void visitCtes(RelationalParser.CtesContext ctx); - @Nonnull @Override LogicalOperator visitNamedQuery(RelationalParser.NamedQueryContext ctx); @Override - LogicalOperator visitTableFunction(@Nonnull RelationalParser.TableFunctionContext ctx); + LogicalOperator visitTableFunction(RelationalParser.TableFunctionContext ctx); @Override Expressions visitNamedOrUnnamedFunctionArgs(RelationalParser.NamedOrUnnamedFunctionArgsContext ctx); @@ -279,731 +235,559 @@ public interface TypedVisitor extends RelationalParserVisitor { @Override Identifier visitTableFunctionName(RelationalParser.TableFunctionNameContext ctx); - @Nonnull @Override - Expression visitContinuationAtom(@Nonnull RelationalParser.ContinuationAtomContext ctx); + Expression visitContinuationAtom(RelationalParser.ContinuationAtomContext ctx); - @Nonnull @Override - LogicalOperator visitQueryTermDefault(@Nonnull RelationalParser.QueryTermDefaultContext ctx); + LogicalOperator visitQueryTermDefault(RelationalParser.QueryTermDefaultContext ctx); - @Nonnull @Override LogicalOperator visitSetQuery(RelationalParser.SetQueryContext ctx); - @Nonnull @Override - LogicalOperator visitInsertStatementValueSelect(@Nonnull RelationalParser.InsertStatementValueSelectContext ctx); + LogicalOperator visitInsertStatementValueSelect(RelationalParser.InsertStatementValueSelectContext ctx); - @Nonnull @Override - LogicalOperator visitInsertStatementValueValues(@Nonnull RelationalParser.InsertStatementValueValuesContext ctx); + LogicalOperator visitInsertStatementValueValues(RelationalParser.InsertStatementValueValuesContext ctx); - @Nonnull @Override - Expressions visitUpdatedElement(@Nonnull RelationalParser.UpdatedElementContext ctx); + Expressions visitUpdatedElement(RelationalParser.UpdatedElementContext ctx); - @Nonnull @Override - Object visitAssignmentField(@Nonnull RelationalParser.AssignmentFieldContext ctx); + Object visitAssignmentField(RelationalParser.AssignmentFieldContext ctx); - @Nonnull @Override - LogicalOperator visitUpdateStatement(@Nonnull RelationalParser.UpdateStatementContext ctx); + LogicalOperator visitUpdateStatement(RelationalParser.UpdateStatementContext ctx); - @Nonnull @Override - List visitOrderByClause(@Nonnull RelationalParser.OrderByClauseContext ctx); + List visitOrderByClause(RelationalParser.OrderByClauseContext ctx); - @Nonnull @Override - OrderByExpression visitOrderByExpression(@Nonnull RelationalParser.OrderByExpressionContext ctx); + OrderByExpression visitOrderByExpression(RelationalParser.OrderByExpressionContext ctx); @Override @Nullable - Void visitTableSources(@Nonnull RelationalParser.TableSourcesContext ctx); + Void visitTableSources(RelationalParser.TableSourcesContext ctx); @Nullable @Override - Void visitTableSourceBase(@Nonnull RelationalParser.TableSourceBaseContext ctx); + Void visitTableSourceBase(RelationalParser.TableSourceBaseContext ctx); - @Nonnull @Override - LogicalOperator visitAtomTableItem(@Nonnull RelationalParser.AtomTableItemContext ctx); + LogicalOperator visitAtomTableItem(RelationalParser.AtomTableItemContext ctx); - @Nonnull @Override - LogicalOperator visitSubqueryTableItem(@Nonnull RelationalParser.SubqueryTableItemContext ctx); + LogicalOperator visitSubqueryTableItem(RelationalParser.SubqueryTableItemContext ctx); - @Nonnull @Override - LogicalOperator visitInlineTableItem(@Nonnull RelationalParser.InlineTableItemContext ctx); + LogicalOperator visitInlineTableItem(RelationalParser.InlineTableItemContext ctx); @Override - LogicalOperator visitTableValuedFunction(@Nonnull RelationalParser.TableValuedFunctionContext ctx); + LogicalOperator visitTableValuedFunction(RelationalParser.TableValuedFunctionContext ctx); - @Nonnull @Override - Set visitIndexHint(@Nonnull RelationalParser.IndexHintContext ctx); + Set visitIndexHint(RelationalParser.IndexHintContext ctx); - @Nonnull @Override - Object visitIndexHintType(@Nonnull RelationalParser.IndexHintTypeContext ctx); + Object visitIndexHintType(RelationalParser.IndexHintTypeContext ctx); - @Nonnull @Override NonnullPair visitInlineTableDefinition(RelationalParser.InlineTableDefinitionContext ctx); @Nullable @Override - Object visitInnerJoin(@Nonnull RelationalParser.InnerJoinContext ctx); + Object visitInnerJoin(RelationalParser.InnerJoinContext ctx); - @Nonnull @Override - Object visitStraightJoin(@Nonnull RelationalParser.StraightJoinContext ctx); + Object visitStraightJoin(RelationalParser.StraightJoinContext ctx); @Nullable @Override - Object visitOuterJoin(@Nonnull RelationalParser.OuterJoinContext ctx); + Object visitOuterJoin(RelationalParser.OuterJoinContext ctx); - @Nonnull @Override - Object visitNaturalJoin(@Nonnull RelationalParser.NaturalJoinContext ctx); + Object visitNaturalJoin(RelationalParser.NaturalJoinContext ctx); - @Nonnull @Override - LogicalOperator visitSimpleTable(@Nonnull RelationalParser.SimpleTableContext ctx); + LogicalOperator visitSimpleTable(RelationalParser.SimpleTableContext ctx); - @Nonnull @Override LogicalOperator visitParenthesisQuery(RelationalParser.ParenthesisQueryContext ctx); - @Nonnull @Override - Expressions visitSelectElements(@Nonnull RelationalParser.SelectElementsContext ctx); + Expressions visitSelectElements(RelationalParser.SelectElementsContext ctx); - @Nonnull @Override - Expression visitSelectStarElement(@Nonnull RelationalParser.SelectStarElementContext ctx); + Expression visitSelectStarElement(RelationalParser.SelectStarElementContext ctx); - @Nonnull @Override - Object visitSelectQualifierStarElement(@Nonnull RelationalParser.SelectQualifierStarElementContext ctx); + Object visitSelectQualifierStarElement(RelationalParser.SelectQualifierStarElementContext ctx); - @Nonnull @Override - Expression visitSelectExpressionElement(@Nonnull RelationalParser.SelectExpressionElementContext ctx); + Expression visitSelectExpressionElement(RelationalParser.SelectExpressionElementContext ctx); @Override @Nullable - Void visitFromClause(@Nonnull RelationalParser.FromClauseContext ctx); + Void visitFromClause(RelationalParser.FromClauseContext ctx); - @Nonnull @Override - Expressions visitGroupByClause(@Nonnull RelationalParser.GroupByClauseContext ctx); + Expressions visitGroupByClause(RelationalParser.GroupByClauseContext ctx); - @Nonnull @Override - Expression visitWhereExpr(@Nonnull RelationalParser.WhereExprContext ctx); + Expression visitWhereExpr(RelationalParser.WhereExprContext ctx); - @Nonnull @Override - Expression visitHavingClause(@Nonnull RelationalParser.HavingClauseContext ctx); + Expression visitHavingClause(RelationalParser.HavingClauseContext ctx); - @Nonnull @Override Expression visitQualifyClause(RelationalParser.QualifyClauseContext ctx); - @Nonnull @Override - Expression visitGroupByItem(@Nonnull RelationalParser.GroupByItemContext ctx); + Expression visitGroupByItem(RelationalParser.GroupByItemContext ctx); - @Nonnull @Override - Expression visitLimitClause(@Nonnull RelationalParser.LimitClauseContext ctx); + Expression visitLimitClause(RelationalParser.LimitClauseContext ctx); - @Nonnull @Override - Expression visitLimitClauseAtom(@Nonnull RelationalParser.LimitClauseAtomContext ctx); + Expression visitLimitClauseAtom(RelationalParser.LimitClauseAtomContext ctx); - @Nonnull @Override - Object visitStatementOptions(@Nonnull RelationalParser.StatementOptionsContext ctx); + Object visitStatementOptions(RelationalParser.StatementOptionsContext ctx); - @Nonnull @Override - Object visitStatementOption(@Nonnull RelationalParser.StatementOptionContext ctx); + Object visitStatementOption(RelationalParser.StatementOptionContext ctx); - @Nonnull @Override - Object visitStartTransaction(@Nonnull RelationalParser.StartTransactionContext ctx); + Object visitStartTransaction(RelationalParser.StartTransactionContext ctx); - @Nonnull @Override - Object visitCommitStatement(@Nonnull RelationalParser.CommitStatementContext ctx); + Object visitCommitStatement(RelationalParser.CommitStatementContext ctx); - @Nonnull @Override - Object visitRollbackStatement(@Nonnull RelationalParser.RollbackStatementContext ctx); + Object visitRollbackStatement(RelationalParser.RollbackStatementContext ctx); - @Nonnull @Override - Object visitSetAutocommitStatement(@Nonnull RelationalParser.SetAutocommitStatementContext ctx); + Object visitSetAutocommitStatement(RelationalParser.SetAutocommitStatementContext ctx); - @Nonnull @Override - Object visitSetTransactionStatement(@Nonnull RelationalParser.SetTransactionStatementContext ctx); + Object visitSetTransactionStatement(RelationalParser.SetTransactionStatementContext ctx); - @Nonnull @Override - Object visitTransactionOption(@Nonnull RelationalParser.TransactionOptionContext ctx); + Object visitTransactionOption(RelationalParser.TransactionOptionContext ctx); - @Nonnull @Override - Object visitTransactionLevel(@Nonnull RelationalParser.TransactionLevelContext ctx); + Object visitTransactionLevel(RelationalParser.TransactionLevelContext ctx); - @Nonnull @Override - Object visitPrepareStatement(@Nonnull RelationalParser.PrepareStatementContext ctx); + Object visitPrepareStatement(RelationalParser.PrepareStatementContext ctx); - @Nonnull @Override - Object visitExecuteStatement(@Nonnull RelationalParser.ExecuteStatementContext ctx); + Object visitExecuteStatement(RelationalParser.ExecuteStatementContext ctx); - @Nonnull @Override - QueryPlan.MetadataQueryPlan visitShowDatabasesStatement(@Nonnull RelationalParser.ShowDatabasesStatementContext ctx); + QueryPlan.MetadataQueryPlan visitShowDatabasesStatement(RelationalParser.ShowDatabasesStatementContext ctx); - @Nonnull @Override - QueryPlan.MetadataQueryPlan visitShowSchemaTemplatesStatement(@Nonnull RelationalParser.ShowSchemaTemplatesStatementContext ctx); + QueryPlan.MetadataQueryPlan visitShowSchemaTemplatesStatement(RelationalParser.ShowSchemaTemplatesStatementContext ctx); - @Nonnull @Override - Object visitSetVariable(@Nonnull RelationalParser.SetVariableContext ctx); + Object visitSetVariable(RelationalParser.SetVariableContext ctx); - @Nonnull @Override - Object visitSetCharset(@Nonnull RelationalParser.SetCharsetContext ctx); + Object visitSetCharset(RelationalParser.SetCharsetContext ctx); - @Nonnull @Override - Object visitSetNames(@Nonnull RelationalParser.SetNamesContext ctx); + Object visitSetNames(RelationalParser.SetNamesContext ctx); - @Nonnull @Override - Object visitSetTransaction(@Nonnull RelationalParser.SetTransactionContext ctx); + Object visitSetTransaction(RelationalParser.SetTransactionContext ctx); - @Nonnull @Override - Object visitSetAutocommit(@Nonnull RelationalParser.SetAutocommitContext ctx); + Object visitSetAutocommit(RelationalParser.SetAutocommitContext ctx); - @Nonnull @Override - Object visitSetNewValueInsideTrigger(@Nonnull RelationalParser.SetNewValueInsideTriggerContext ctx); + Object visitSetNewValueInsideTrigger(RelationalParser.SetNewValueInsideTriggerContext ctx); - @Nonnull @Override - Object visitVariableClause(@Nonnull RelationalParser.VariableClauseContext ctx); + Object visitVariableClause(RelationalParser.VariableClauseContext ctx); - @Nonnull @Override - Object visitKillStatement(@Nonnull RelationalParser.KillStatementContext ctx); + Object visitKillStatement(RelationalParser.KillStatementContext ctx); - @Nonnull @Override - Object visitResetStatement(@Nonnull RelationalParser.ResetStatementContext ctx); + Object visitResetStatement(RelationalParser.ResetStatementContext ctx); - @Nonnull @Override - Object visitTableIndexes(@Nonnull RelationalParser.TableIndexesContext ctx); + Object visitTableIndexes(RelationalParser.TableIndexesContext ctx); - @Nonnull @Override - Object visitLoadedTableIndexes(@Nonnull RelationalParser.LoadedTableIndexesContext ctx); + Object visitLoadedTableIndexes(RelationalParser.LoadedTableIndexesContext ctx); - @Nonnull @Override - QueryPlan.MetadataQueryPlan visitSimpleDescribeSchemaStatement(@Nonnull RelationalParser.SimpleDescribeSchemaStatementContext ctx); + QueryPlan.MetadataQueryPlan visitSimpleDescribeSchemaStatement(RelationalParser.SimpleDescribeSchemaStatementContext ctx); - @Nonnull @Override - QueryPlan.MetadataQueryPlan visitSimpleDescribeSchemaTemplateStatement(@Nonnull RelationalParser.SimpleDescribeSchemaTemplateStatementContext ctx); + QueryPlan.MetadataQueryPlan visitSimpleDescribeSchemaTemplateStatement(RelationalParser.SimpleDescribeSchemaTemplateStatementContext ctx); - @Nonnull @Override - QueryPlan.LogicalQueryPlan visitFullDescribeStatement(@Nonnull RelationalParser.FullDescribeStatementContext ctx); + QueryPlan.LogicalQueryPlan visitFullDescribeStatement(RelationalParser.FullDescribeStatementContext ctx); - @Nonnull @Override - Object visitHelpStatement(@Nonnull RelationalParser.HelpStatementContext ctx); + Object visitHelpStatement(RelationalParser.HelpStatementContext ctx); - @Nonnull @Override - Object visitDescribeStatements(@Nonnull RelationalParser.DescribeStatementsContext ctx); + Object visitDescribeStatements(RelationalParser.DescribeStatementsContext ctx); - @Nonnull @Override - Object visitDescribeConnection(@Nonnull RelationalParser.DescribeConnectionContext ctx); + Object visitDescribeConnection(RelationalParser.DescribeConnectionContext ctx); - @Nonnull @Override - Identifier visitFullId(@Nonnull RelationalParser.FullIdContext ctx); + Identifier visitFullId(RelationalParser.FullIdContext ctx); - @Nonnull @Override - Identifier visitTableName(@Nonnull RelationalParser.TableNameContext ctx); + Identifier visitTableName(RelationalParser.TableNameContext ctx); - @Nonnull @Override - Expression visitFullColumnName(@Nonnull RelationalParser.FullColumnNameContext ctx); + Expression visitFullColumnName(RelationalParser.FullColumnNameContext ctx); - @Nonnull @Override - Identifier visitIndexColumnName(@Nonnull RelationalParser.IndexColumnNameContext ctx); + Identifier visitIndexColumnName(RelationalParser.IndexColumnNameContext ctx); - @Nonnull @Override - Identifier visitCharsetName(@Nonnull RelationalParser.CharsetNameContext ctx); + Identifier visitCharsetName(RelationalParser.CharsetNameContext ctx); - @Nonnull @Override - Identifier visitCollationName(@Nonnull RelationalParser.CollationNameContext ctx); + Identifier visitCollationName(RelationalParser.CollationNameContext ctx); - @Nonnull @Override - Identifier visitUid(@Nonnull RelationalParser.UidContext ctx); + Identifier visitUid(RelationalParser.UidContext ctx); - @Nonnull @Override - Identifier visitSimpleId(@Nonnull RelationalParser.SimpleIdContext ctx); + Identifier visitSimpleId(RelationalParser.SimpleIdContext ctx); - @Nonnull @Override - Object visitNullNotnull(@Nonnull RelationalParser.NullNotnullContext ctx); + Object visitNullNotnull(RelationalParser.NullNotnullContext ctx); - @Nonnull @Override - Expression visitDecimalLiteral(@Nonnull RelationalParser.DecimalLiteralContext ctx); + Expression visitDecimalLiteral(RelationalParser.DecimalLiteralContext ctx); - @Nonnull @Override - Expression visitStringLiteral(@Nonnull RelationalParser.StringLiteralContext ctx); + Expression visitStringLiteral(RelationalParser.StringLiteralContext ctx); - @Nonnull @Override - Expression visitBooleanLiteral(@Nonnull RelationalParser.BooleanLiteralContext ctx); + Expression visitBooleanLiteral(RelationalParser.BooleanLiteralContext ctx); - @Nonnull @Override - Expression visitBytesLiteral(@Nonnull RelationalParser.BytesLiteralContext ctx); + Expression visitBytesLiteral(RelationalParser.BytesLiteralContext ctx); - @Nonnull @Override - Expression visitNullLiteral(@Nonnull RelationalParser.NullLiteralContext ctx); + Expression visitNullLiteral(RelationalParser.NullLiteralContext ctx); - @Nonnull @Override - Expression visitStringConstant(@Nonnull RelationalParser.StringConstantContext ctx); + Expression visitStringConstant(RelationalParser.StringConstantContext ctx); - @Nonnull @Override - Expression visitDecimalConstant(@Nonnull RelationalParser.DecimalConstantContext ctx); + Expression visitDecimalConstant(RelationalParser.DecimalConstantContext ctx); - @Nonnull @Override - Expression visitNegativeDecimalConstant(@Nonnull RelationalParser.NegativeDecimalConstantContext ctx); + Expression visitNegativeDecimalConstant(RelationalParser.NegativeDecimalConstantContext ctx); - @Nonnull @Override - Expression visitBytesConstant(@Nonnull RelationalParser.BytesConstantContext ctx); + Expression visitBytesConstant(RelationalParser.BytesConstantContext ctx); - @Nonnull @Override - Expression visitBooleanConstant(@Nonnull RelationalParser.BooleanConstantContext ctx); + Expression visitBooleanConstant(RelationalParser.BooleanConstantContext ctx); - @Nonnull @Override - Expression visitBitStringConstant(@Nonnull RelationalParser.BitStringConstantContext ctx); + Expression visitBitStringConstant(RelationalParser.BitStringConstantContext ctx); - @Nonnull @Override - Expression visitNullConstant(@Nonnull RelationalParser.NullConstantContext ctx); + Expression visitNullConstant(RelationalParser.NullConstantContext ctx); - @Nonnull @Override - Object visitStringDataType(@Nonnull RelationalParser.StringDataTypeContext ctx); + Object visitStringDataType(RelationalParser.StringDataTypeContext ctx); - @Nonnull @Override - Object visitNationalStringDataType(@Nonnull RelationalParser.NationalStringDataTypeContext ctx); + Object visitNationalStringDataType(RelationalParser.NationalStringDataTypeContext ctx); - @Nonnull @Override - Object visitNationalVaryingStringDataType(@Nonnull RelationalParser.NationalVaryingStringDataTypeContext ctx); + Object visitNationalVaryingStringDataType(RelationalParser.NationalVaryingStringDataTypeContext ctx); - @Nonnull @Override - Object visitDimensionDataType(@Nonnull RelationalParser.DimensionDataTypeContext ctx); + Object visitDimensionDataType(RelationalParser.DimensionDataTypeContext ctx); - @Nonnull @Override - Object visitSimpleDataType(@Nonnull RelationalParser.SimpleDataTypeContext ctx); + Object visitSimpleDataType(RelationalParser.SimpleDataTypeContext ctx); - @Nonnull @Override - Object visitCollectionDataType(@Nonnull RelationalParser.CollectionDataTypeContext ctx); + Object visitCollectionDataType(RelationalParser.CollectionDataTypeContext ctx); - @Nonnull @Override - Object visitSpatialDataType(@Nonnull RelationalParser.SpatialDataTypeContext ctx); + Object visitSpatialDataType(RelationalParser.SpatialDataTypeContext ctx); - @Nonnull @Override - Object visitLongVarcharDataType(@Nonnull RelationalParser.LongVarcharDataTypeContext ctx); + Object visitLongVarcharDataType(RelationalParser.LongVarcharDataTypeContext ctx); - @Nonnull @Override - Object visitLongVarbinaryDataType(@Nonnull RelationalParser.LongVarbinaryDataTypeContext ctx); + Object visitLongVarbinaryDataType(RelationalParser.LongVarbinaryDataTypeContext ctx); - @Nonnull @Override - Object visitCollectionOptions(@Nonnull RelationalParser.CollectionOptionsContext ctx); + Object visitCollectionOptions(RelationalParser.CollectionOptionsContext ctx); - @Nonnull @Override - Object visitConvertedDataType(@Nonnull RelationalParser.ConvertedDataTypeContext ctx); + Object visitConvertedDataType(RelationalParser.ConvertedDataTypeContext ctx); - @Nonnull @Override - Object visitLengthOneDimension(@Nonnull RelationalParser.LengthOneDimensionContext ctx); + Object visitLengthOneDimension(RelationalParser.LengthOneDimensionContext ctx); - @Nonnull @Override - Object visitLengthTwoDimension(@Nonnull RelationalParser.LengthTwoDimensionContext ctx); + Object visitLengthTwoDimension(RelationalParser.LengthTwoDimensionContext ctx); - @Nonnull @Override - Object visitLengthTwoOptionalDimension(@Nonnull RelationalParser.LengthTwoOptionalDimensionContext ctx); + Object visitLengthTwoOptionalDimension(RelationalParser.LengthTwoOptionalDimensionContext ctx); - @Nonnull @Override - List visitUidList(@Nonnull RelationalParser.UidListContext ctx); + List visitUidList(RelationalParser.UidListContext ctx); - @Nonnull @Override - Object visitUidWithNestings(@Nonnull RelationalParser.UidWithNestingsContext ctx); + Object visitUidWithNestings(RelationalParser.UidWithNestingsContext ctx); - @Nonnull @Override - CompatibleTypeEvolutionPredicate.FieldAccessTrieNode visitUidListWithNestingsInParens(@Nonnull RelationalParser.UidListWithNestingsInParensContext ctx); + CompatibleTypeEvolutionPredicate.FieldAccessTrieNode visitUidListWithNestingsInParens(RelationalParser.UidListWithNestingsInParensContext ctx); - @Nonnull @Override - CompatibleTypeEvolutionPredicate.FieldAccessTrieNode visitUidListWithNestings(@Nonnull RelationalParser.UidListWithNestingsContext ctx); + CompatibleTypeEvolutionPredicate.FieldAccessTrieNode visitUidListWithNestings(RelationalParser.UidListWithNestingsContext ctx); - @Nonnull @Override - Object visitTables(@Nonnull RelationalParser.TablesContext ctx); + Object visitTables(RelationalParser.TablesContext ctx); - @Nonnull @Override - Object visitIndexColumnNames(@Nonnull RelationalParser.IndexColumnNamesContext ctx); + Object visitIndexColumnNames(RelationalParser.IndexColumnNamesContext ctx); - @Nonnull @Override - Expressions visitExpressions(@Nonnull RelationalParser.ExpressionsContext ctx); + Expressions visitExpressions(RelationalParser.ExpressionsContext ctx); - @Nonnull @Override - Object visitExpressionsWithDefaults(@Nonnull RelationalParser.ExpressionsWithDefaultsContext ctx); + Object visitExpressionsWithDefaults(RelationalParser.ExpressionsWithDefaultsContext ctx); - @Nonnull @Override - Expression visitRecordConstructorForInsert(@Nonnull RelationalParser.RecordConstructorForInsertContext ctx); + Expression visitRecordConstructorForInsert(RelationalParser.RecordConstructorForInsertContext ctx); @Override Expression visitRecordConstructorForInlineTable(RelationalParser.RecordConstructorForInlineTableContext ctx); - @Nonnull @Override - Expression visitRecordConstructor(@Nonnull RelationalParser.RecordConstructorContext ctx); + Expression visitRecordConstructor(RelationalParser.RecordConstructorContext ctx); - @Nonnull @Override - Object visitOfTypeClause(@Nonnull RelationalParser.OfTypeClauseContext ctx); + Object visitOfTypeClause(RelationalParser.OfTypeClauseContext ctx); - @Nonnull @Override - Expression visitArrayConstructor(@Nonnull RelationalParser.ArrayConstructorContext ctx); + Expression visitArrayConstructor(RelationalParser.ArrayConstructorContext ctx); - @Nonnull @Override - Object visitUserVariables(@Nonnull RelationalParser.UserVariablesContext ctx); + Object visitUserVariables(RelationalParser.UserVariablesContext ctx); - @Nonnull @Override - Object visitDefaultValue(@Nonnull RelationalParser.DefaultValueContext ctx); + Object visitDefaultValue(RelationalParser.DefaultValueContext ctx); - @Nonnull @Override - Object visitCurrentTimestamp(@Nonnull RelationalParser.CurrentTimestampContext ctx); + Object visitCurrentTimestamp(RelationalParser.CurrentTimestampContext ctx); - @Nonnull @Override - Object visitExpressionOrDefault(@Nonnull RelationalParser.ExpressionOrDefaultContext ctx); + Object visitExpressionOrDefault(RelationalParser.ExpressionOrDefaultContext ctx); - @Nonnull @Override - Expression visitExpressionWithOptionalName(@Nonnull RelationalParser.ExpressionWithOptionalNameContext ctx); + Expression visitExpressionWithOptionalName(RelationalParser.ExpressionWithOptionalNameContext ctx); @Nullable @Override - Object visitIfExists(@Nonnull RelationalParser.IfExistsContext ctx); + Object visitIfExists(RelationalParser.IfExistsContext ctx); @Nullable @Override - Object visitIfNotExists(@Nonnull RelationalParser.IfNotExistsContext ctx); + Object visitIfNotExists(RelationalParser.IfNotExistsContext ctx); - @Nonnull @Override - Expression visitAggregateFunctionCall(@Nonnull RelationalParser.AggregateFunctionCallContext ctx); + Expression visitAggregateFunctionCall(RelationalParser.AggregateFunctionCallContext ctx); - @Nonnull @Override Expression visitNonAggregateFunctionCall(RelationalParser.NonAggregateFunctionCallContext ctx); - @Nonnull @Override - Expression visitUserDefinedScalarFunctionCall(@Nonnull RelationalParser.UserDefinedScalarFunctionCallContext ctx); + Expression visitUserDefinedScalarFunctionCall(RelationalParser.UserDefinedScalarFunctionCallContext ctx); - @Nonnull @Override - Object visitSpecificFunctionCall(@Nonnull RelationalParser.SpecificFunctionCallContext ctx); + Object visitSpecificFunctionCall(RelationalParser.SpecificFunctionCallContext ctx); - @Nonnull @Override - Expression visitScalarFunctionCall(@Nonnull RelationalParser.ScalarFunctionCallContext ctx); + Expression visitScalarFunctionCall(RelationalParser.ScalarFunctionCallContext ctx); - @Nonnull @Override - Object visitSimpleFunctionCall(@Nonnull RelationalParser.SimpleFunctionCallContext ctx); + Object visitSimpleFunctionCall(RelationalParser.SimpleFunctionCallContext ctx); - @Nonnull @Override - Object visitDataTypeFunctionCall(@Nonnull RelationalParser.DataTypeFunctionCallContext ctx); + Object visitDataTypeFunctionCall(RelationalParser.DataTypeFunctionCallContext ctx); - @Nonnull @Override - Object visitValuesFunctionCall(@Nonnull RelationalParser.ValuesFunctionCallContext ctx); + Object visitValuesFunctionCall(RelationalParser.ValuesFunctionCallContext ctx); - @Nonnull @Override - Object visitCaseExpressionFunctionCall(@Nonnull RelationalParser.CaseExpressionFunctionCallContext ctx); + Object visitCaseExpressionFunctionCall(RelationalParser.CaseExpressionFunctionCallContext ctx); - @Nonnull @Override - Expression visitCaseFunctionCall(@Nonnull RelationalParser.CaseFunctionCallContext ctx); + Expression visitCaseFunctionCall(RelationalParser.CaseFunctionCallContext ctx); - @Nonnull @Override - Object visitCharFunctionCall(@Nonnull RelationalParser.CharFunctionCallContext ctx); + Object visitCharFunctionCall(RelationalParser.CharFunctionCallContext ctx); - @Nonnull @Override - Object visitPositionFunctionCall(@Nonnull RelationalParser.PositionFunctionCallContext ctx); + Object visitPositionFunctionCall(RelationalParser.PositionFunctionCallContext ctx); - @Nonnull @Override - Object visitSubstrFunctionCall(@Nonnull RelationalParser.SubstrFunctionCallContext ctx); + Object visitSubstrFunctionCall(RelationalParser.SubstrFunctionCallContext ctx); - @Nonnull @Override - Object visitTrimFunctionCall(@Nonnull RelationalParser.TrimFunctionCallContext ctx); + Object visitTrimFunctionCall(RelationalParser.TrimFunctionCallContext ctx); - @Nonnull @Override - Object visitWeightFunctionCall(@Nonnull RelationalParser.WeightFunctionCallContext ctx); + Object visitWeightFunctionCall(RelationalParser.WeightFunctionCallContext ctx); - @Nonnull @Override - Object visitExtractFunctionCall(@Nonnull RelationalParser.ExtractFunctionCallContext ctx); + Object visitExtractFunctionCall(RelationalParser.ExtractFunctionCallContext ctx); - @Nonnull @Override - Object visitGetFormatFunctionCall(@Nonnull RelationalParser.GetFormatFunctionCallContext ctx); + Object visitGetFormatFunctionCall(RelationalParser.GetFormatFunctionCallContext ctx); - @Nonnull @Override - Object visitCaseFuncAlternative(@Nonnull RelationalParser.CaseFuncAlternativeContext ctx); + Object visitCaseFuncAlternative(RelationalParser.CaseFuncAlternativeContext ctx); - @Nonnull @Override - Object visitLevelWeightList(@Nonnull RelationalParser.LevelWeightListContext ctx); + Object visitLevelWeightList(RelationalParser.LevelWeightListContext ctx); - @Nonnull @Override - Object visitLevelWeightRange(@Nonnull RelationalParser.LevelWeightRangeContext ctx); + Object visitLevelWeightRange(RelationalParser.LevelWeightRangeContext ctx); - @Nonnull @Override - Object visitLevelInWeightListElement(@Nonnull RelationalParser.LevelInWeightListElementContext ctx); + Object visitLevelInWeightListElement(RelationalParser.LevelInWeightListElementContext ctx); - @Nonnull @Override - Expression visitAggregateWindowedFunction(@Nonnull RelationalParser.AggregateWindowedFunctionContext ctx); + Expression visitAggregateWindowedFunction(RelationalParser.AggregateWindowedFunctionContext ctx); - @Nonnull @Override - Boolean visitNullTreatmentClause(@Nonnull RelationalParser.NullTreatmentClauseContext ctx); + Boolean visitNullTreatmentClause(RelationalParser.NullTreatmentClauseContext ctx); - @Nonnull @Override - Expression visitNonAggregateWindowedFunction(@Nonnull RelationalParser.NonAggregateWindowedFunctionContext ctx); + Expression visitNonAggregateWindowedFunction(RelationalParser.NonAggregateWindowedFunctionContext ctx); - @Nonnull @Override - WindowSpecExpression visitOverClause(@Nonnull RelationalParser.OverClauseContext ctx); + WindowSpecExpression visitOverClause(RelationalParser.OverClauseContext ctx); - @Nonnull @Override Expressions visitPartitionClause(RelationalParser.PartitionClauseContext ctx); - @Nonnull @Override - Object visitWindowName(@Nonnull RelationalParser.WindowNameContext ctx); + Object visitWindowName(RelationalParser.WindowNameContext ctx); - @Nonnull @Override Expressions visitWindowOptionsClause(RelationalParser.WindowOptionsClauseContext ctx); - @Nonnull @Override Expression visitWindowOption(RelationalParser.WindowOptionContext ctx); - @Nonnull @Override - Object visitScalarFunctionName(@Nonnull RelationalParser.ScalarFunctionNameContext ctx); + Object visitScalarFunctionName(RelationalParser.ScalarFunctionNameContext ctx); - @Nonnull @Override - Expressions visitFunctionArgs(@Nonnull RelationalParser.FunctionArgsContext ctx); + Expressions visitFunctionArgs(RelationalParser.FunctionArgsContext ctx); - @Nonnull @Override - Object visitFunctionArg(@Nonnull RelationalParser.FunctionArgContext ctx); + Object visitFunctionArg(RelationalParser.FunctionArgContext ctx); @Override Expression visitNamedFunctionArg(RelationalParser.NamedFunctionArgContext ctx); - @Nonnull @Override - Expression visitNotExpression(@Nonnull RelationalParser.NotExpressionContext ctx); + Expression visitNotExpression(RelationalParser.NotExpressionContext ctx); - @Nonnull @Override - Expression visitLogicalExpression(@Nonnull RelationalParser.LogicalExpressionContext ctx); + Expression visitLogicalExpression(RelationalParser.LogicalExpressionContext ctx); - @Nonnull @Override - Expression visitPredicatedExpression(@Nonnull RelationalParser.PredicatedExpressionContext ctx); + Expression visitPredicatedExpression(RelationalParser.PredicatedExpressionContext ctx); - @Nonnull @Override - Expression visitBinaryComparisonPredicate(@Nonnull RelationalParser.BinaryComparisonPredicateContext ctx); + Expression visitBinaryComparisonPredicate(RelationalParser.BinaryComparisonPredicateContext ctx); @Override - Expression visitSubscriptExpression(@Nonnull RelationalParser.SubscriptExpressionContext ctx); + Expression visitSubscriptExpression(RelationalParser.SubscriptExpressionContext ctx); - @Nonnull @Override - Expression visitInList(@Nonnull RelationalParser.InListContext ctx); + Expression visitInList(RelationalParser.InListContext ctx); - @Nonnull @Override - Object visitConstantExpressionAtom(@Nonnull RelationalParser.ConstantExpressionAtomContext ctx); + Object visitConstantExpressionAtom(RelationalParser.ConstantExpressionAtomContext ctx); - @Nonnull @Override - Expression visitFunctionCallExpressionAtom(@Nonnull RelationalParser.FunctionCallExpressionAtomContext ctx); + Expression visitFunctionCallExpressionAtom(RelationalParser.FunctionCallExpressionAtomContext ctx); - @Nonnull @Override - Object visitFullColumnNameExpressionAtom(@Nonnull RelationalParser.FullColumnNameExpressionAtomContext ctx); + Object visitFullColumnNameExpressionAtom(RelationalParser.FullColumnNameExpressionAtomContext ctx); - @Nonnull @Override - Expression visitBitExpressionAtom(@Nonnull RelationalParser.BitExpressionAtomContext ctx); + Expression visitBitExpressionAtom(RelationalParser.BitExpressionAtomContext ctx); - @Nonnull @Override - Expression visitPreparedStatementParameterAtom(@Nonnull RelationalParser.PreparedStatementParameterAtomContext ctx); + Expression visitPreparedStatementParameterAtom(RelationalParser.PreparedStatementParameterAtomContext ctx); - @Nonnull @Override - Object visitRecordConstructorExpressionAtom(@Nonnull RelationalParser.RecordConstructorExpressionAtomContext ctx); + Object visitRecordConstructorExpressionAtom(RelationalParser.RecordConstructorExpressionAtomContext ctx); - @Nonnull @Override - Object visitArrayConstructorExpressionAtom(@Nonnull RelationalParser.ArrayConstructorExpressionAtomContext ctx); + Object visitArrayConstructorExpressionAtom(RelationalParser.ArrayConstructorExpressionAtomContext ctx); - @Nonnull @Override - Expression visitMathExpressionAtom(@Nonnull RelationalParser.MathExpressionAtomContext ctx); + Expression visitMathExpressionAtom(RelationalParser.MathExpressionAtomContext ctx); - @Nonnull @Override - Expression visitExistsExpressionAtom(@Nonnull RelationalParser.ExistsExpressionAtomContext ctx); + Expression visitExistsExpressionAtom(RelationalParser.ExistsExpressionAtomContext ctx); - @Nonnull @Override - Expression visitPreparedStatementParameter(@Nonnull RelationalParser.PreparedStatementParameterContext ctx); + Expression visitPreparedStatementParameter(RelationalParser.PreparedStatementParameterContext ctx); - @Nonnull @Override - Object visitUnaryOperator(@Nonnull RelationalParser.UnaryOperatorContext ctx); + Object visitUnaryOperator(RelationalParser.UnaryOperatorContext ctx); - @Nonnull @Override - Object visitComparisonOperator(@Nonnull RelationalParser.ComparisonOperatorContext ctx); + Object visitComparisonOperator(RelationalParser.ComparisonOperatorContext ctx); - @Nonnull @Override - Object visitLogicalOperator(@Nonnull RelationalParser.LogicalOperatorContext ctx); + Object visitLogicalOperator(RelationalParser.LogicalOperatorContext ctx); - @Nonnull @Override - Object visitBitOperator(@Nonnull RelationalParser.BitOperatorContext ctx); + Object visitBitOperator(RelationalParser.BitOperatorContext ctx); - @Nonnull @Override - Object visitMathOperator(@Nonnull RelationalParser.MathOperatorContext ctx); + Object visitMathOperator(RelationalParser.MathOperatorContext ctx); - @Nonnull @Override - Object visitJsonOperator(@Nonnull RelationalParser.JsonOperatorContext ctx); + Object visitJsonOperator(RelationalParser.JsonOperatorContext ctx); - @Nonnull @Override - Object visitCharsetNameBase(@Nonnull RelationalParser.CharsetNameBaseContext ctx); + Object visitCharsetNameBase(RelationalParser.CharsetNameBaseContext ctx); - @Nonnull @Override - Object visitIntervalTypeBase(@Nonnull RelationalParser.IntervalTypeBaseContext ctx); + Object visitIntervalTypeBase(RelationalParser.IntervalTypeBaseContext ctx); - @Nonnull @Override - Object visitKeywordsCanBeId(@Nonnull RelationalParser.KeywordsCanBeIdContext ctx); + Object visitKeywordsCanBeId(RelationalParser.KeywordsCanBeIdContext ctx); - @Nonnull @Override - Object visitFunctionNameBase(@Nonnull RelationalParser.FunctionNameBaseContext ctx); + Object visitFunctionNameBase(RelationalParser.FunctionNameBaseContext ctx); - @Nonnull @Override - Object visitFunctionNameKeyword(@Nonnull RelationalParser.FunctionNameKeywordContext ctx); + Object visitFunctionNameKeyword(RelationalParser.FunctionNameKeywordContext ctx); - @Nonnull @Override - Object visitExecuteContinuationStatement(@Nonnull RelationalParser.ExecuteContinuationStatementContext ctx); + Object visitExecuteContinuationStatement(RelationalParser.ExecuteContinuationStatementContext ctx); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/package-info.java index 2c91a042faf..fef103dbfc4 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/package-info.java @@ -22,4 +22,7 @@ * This package contains all plan generation visitors. */ +@NullMarked package com.apple.foundationdb.relational.recordlayer.query.visitors; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizerTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizerTests.java index f9a83a954b4..4db357bf5f0 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizerTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizerTests.java @@ -50,9 +50,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.sql.SQLException; import java.util.Base64; import java.util.EnumSet; @@ -83,7 +81,6 @@ */ public class AstNormalizerTests { - @Nonnull private static final RecordLayerSchemaTemplate fakeSchemaTemplate = RecordLayerSchemaTemplate .newBuilder() .setName("testTemplate") @@ -98,140 +95,139 @@ public class AstNormalizerTests { .build()) .build(); - @Nonnull private static final PlannerConfiguration plannerConfiguration = PlannerConfiguration.ofAllAvailableIndexes(); - private static void validate(@Nonnull final String query, - @Nonnull final String expectedCanonicalRepresentation) throws RelationalException { + private static void validate(final String query, + final String expectedCanonicalRepresentation) throws RelationalException { validate(List.of(query), PreparedParams.empty(), expectedCanonicalRepresentation); } - private static void validate(@Nonnull final String query, - @Nonnull final PreparedParams preparedStatementParameters, - @Nonnull final String expectedCanonicalRepresentation) throws RelationalException { + private static void validate(final String query, + final PreparedParams preparedStatementParameters, + final String expectedCanonicalRepresentation) throws RelationalException { validate(List.of(query), preparedStatementParameters, expectedCanonicalRepresentation); } - private static void validate(@Nonnull final List queries, - @Nonnull final String expectedCanonicalRepresentation) throws RelationalException { + private static void validate(final List queries, + final String expectedCanonicalRepresentation) throws RelationalException { validate(queries, PreparedParams.empty(), expectedCanonicalRepresentation, queries.stream().map(q -> Map.of()).collect(Collectors.toList())); } - private static void validate(@Nonnull final List queries, - @Nonnull final PreparedParams preparedStatementParameters, - @Nonnull final String expectedCanonicalRepresentation) throws RelationalException { + private static void validate(final List queries, + final PreparedParams preparedStatementParameters, + final String expectedCanonicalRepresentation) throws RelationalException { validate(queries, preparedStatementParameters, expectedCanonicalRepresentation, queries.stream().map(q -> Map.of()).collect(Collectors.toList())); } - private static void validate(@Nonnull final String query, - @Nonnull final String expectedCanonicalRepresentation, - @Nonnull final Map expectedParameters) throws RelationalException { + private static void validate(final String query, + final String expectedCanonicalRepresentation, + final Map expectedParameters) throws RelationalException { validate(List.of(query), PreparedParams.empty(), expectedCanonicalRepresentation, List.of(expectedParameters)); } - private static void validate(@Nonnull final String query, - @Nonnull final PreparedParams preparedStatementParameters, - @Nonnull final String expectedCanonicalRepresentation, - @Nonnull final Map expectedParameters) throws RelationalException { + private static void validate(final String query, + final PreparedParams preparedStatementParameters, + final String expectedCanonicalRepresentation, + final Map expectedParameters) throws RelationalException { validate(List.of(query), preparedStatementParameters, expectedCanonicalRepresentation, List.of(expectedParameters)); } - private static void validate(@Nonnull final List queries, - @Nonnull final String expectedCanonicalRepresentation, - @Nonnull final List> expectedParameters) throws RelationalException { + private static void validate(final List queries, + final String expectedCanonicalRepresentation, + final List> expectedParameters) throws RelationalException { validate(queries, PreparedParams.empty(), expectedCanonicalRepresentation, expectedParameters, null); } - private static void validate(@Nonnull final List queries, - @Nonnull final PreparedParams preparedStatementParameters, - @Nonnull final String expectedCanonicalRepresentation, - @Nonnull final List> expectedParameters) throws RelationalException { + private static void validate(final List queries, + final PreparedParams preparedStatementParameters, + final String expectedCanonicalRepresentation, + final List> expectedParameters) throws RelationalException { validate(queries, preparedStatementParameters, expectedCanonicalRepresentation, expectedParameters, null); } - private static void validate(@Nonnull final String query, - @Nonnull final String expectedCanonicalRepresentation, - @Nonnull final Map expectedParameters, + private static void validate(final String query, + final String expectedCanonicalRepresentation, + final Map expectedParameters, @Nullable final String expectedContinuation) throws RelationalException { validate(List.of(query), PreparedParams.empty(), expectedCanonicalRepresentation, List.of(expectedParameters), expectedContinuation, -1); } - private static void validate(@Nonnull final String query, - @Nonnull final PreparedParams preparedStatementParameters, - @Nonnull final String expectedCanonicalRepresentation, - @Nonnull final Map expectedParameters, + private static void validate(final String query, + final PreparedParams preparedStatementParameters, + final String expectedCanonicalRepresentation, + final Map expectedParameters, @Nullable final String expectedContinuation) throws RelationalException { validate(List.of(query), preparedStatementParameters, expectedCanonicalRepresentation, List.of(expectedParameters), expectedContinuation, -1); } - private static void validate(@Nonnull final List queries, - @Nonnull final String expectedCanonicalRepresentation, - @Nonnull final List> expectedParameters, + private static void validate(final List queries, + final String expectedCanonicalRepresentation, + final List> expectedParameters, @Nullable final String expectedContinuation) throws RelationalException { validate(queries, PreparedParams.empty(), expectedCanonicalRepresentation, expectedParameters, expectedContinuation, -1); } - private static void validate(@Nonnull final List queries, - @Nonnull final PreparedParams preparedStatementParameters, - @Nonnull final String expectedCanonicalRepresentation, - @Nonnull final List> expectedParameters, + private static void validate(final List queries, + final PreparedParams preparedStatementParameters, + final String expectedCanonicalRepresentation, + final List> expectedParameters, @Nullable final String expectedContinuation) throws RelationalException { validate(queries, preparedStatementParameters, expectedCanonicalRepresentation, expectedParameters, expectedContinuation, -1); } - private static void validate(@Nonnull final String query, - @Nonnull final String expectedCanonicalRepresentation, - @Nonnull final Map expectedParameters, + private static void validate(final String query, + final String expectedCanonicalRepresentation, + final Map expectedParameters, int limit) throws RelationalException { validate(List.of(query), PreparedParams.empty(), expectedCanonicalRepresentation, List.of(expectedParameters), null, limit); } - private static void validate(@Nonnull final String query, - @Nonnull final PreparedParams preparedStatementParameters, - @Nonnull final String expectedCanonicalRepresentation, - @Nonnull final Map expectedParameters, + private static void validate(final String query, + final PreparedParams preparedStatementParameters, + final String expectedCanonicalRepresentation, + final Map expectedParameters, int limit) throws RelationalException { validate(List.of(query), preparedStatementParameters, expectedCanonicalRepresentation, List.of(expectedParameters), null, limit); } - private static void validate(@Nonnull final List queries, - @Nonnull final String expectedCanonicalRepresentation, - @Nonnull final List> expectedParameters, + private static void validate(final List queries, + final String expectedCanonicalRepresentation, + final List> expectedParameters, int limit) throws RelationalException { validate(queries, PreparedParams.empty(), expectedCanonicalRepresentation, expectedParameters, null, limit); } - private static void validate(@Nonnull final List queries, - @Nonnull final PreparedParams preparedStatementParameters, - @Nonnull final String expectedCanonicalRepresentation, - @Nonnull final List> expectedParameters, + private static void validate(final List queries, + final PreparedParams preparedStatementParameters, + final String expectedCanonicalRepresentation, + final List> expectedParameters, int limit) throws RelationalException { validate(queries, preparedStatementParameters, expectedCanonicalRepresentation, expectedParameters, null, limit); } - private static void validate(@Nonnull final List queries, - @Nonnull final PreparedParams preparedParameters, - @Nonnull final String expectedCanonicalRepresentation, - @Nonnull final List> expectedParametersList, + private static void validate(final List queries, + final PreparedParams preparedParameters, + final String expectedCanonicalRepresentation, + final List> expectedParametersList, @Nullable final String expectedContinuation, int limit) throws RelationalException { validate(queries, preparedParameters, expectedCanonicalRepresentation, expectedParametersList, expectedContinuation, limit, null); } - private static void validate(@Nonnull final List queries, - @Nonnull final PreparedParams preparedParameters, - @Nonnull final String expectedCanonicalRepresentation, - @Nonnull final List> expectedParametersList, + private static void validate(final List queries, + final PreparedParams preparedParameters, + final String expectedCanonicalRepresentation, + final List> expectedParametersList, @Nullable final String expectedContinuation, int limit, @Nullable EnumSet queryCachingFlags) throws RelationalException { validate(queries, preparedParameters, expectedCanonicalRepresentation, expectedParametersList, expectedContinuation, limit, queryCachingFlags, null); } - private static void validate(@Nonnull final List queries, - @Nonnull final PreparedParams preparedParameters, - @Nonnull final String expectedCanonicalRepresentation, - @Nonnull final List> expectedParametersList, + private static void validate(final List queries, + final PreparedParams preparedParameters, + final String expectedCanonicalRepresentation, + final List> expectedParametersList, @Nullable final String expectedContinuation, int limit, @Nullable EnumSet queryCachingFlags, @@ -243,16 +239,16 @@ private static void validate(@Nonnull final List queries, limit, queryCachingFlags, queryOptions, schemaTemplates.build(), ""); } - private static void validate(@Nonnull final List queries, - @Nonnull final PreparedParams preparedParameters, - @Nonnull final String expectedCanonicalRepresentation, - @Nonnull final List> expectedParametersList, + private static void validate(final List queries, + final PreparedParams preparedParameters, + final String expectedCanonicalRepresentation, + final List> expectedParametersList, @Nullable final String expectedContinuation, int limit, @Nullable EnumSet queryCachingFlags, @Nullable Map queryOptions, - @Nonnull final List schemaTemplates, - @Nonnull final String auxiliaryMetadata) throws RelationalException { + final List schemaTemplates, + final String auxiliaryMetadata) throws RelationalException { Assert.thatUnchecked(!queries.isEmpty()); Assert.thatUnchecked(queries.size() == expectedParametersList.size()); Integer queryHash = null; @@ -308,7 +304,7 @@ private static void validate(@Nonnull final List queries, } } - private static void shouldFail(@Nonnull final String query, @Nonnull final String errorMessage) { + private static void shouldFail(final String query, final String errorMessage) { try { AstNormalizer.normalizeAst(fakeSchemaTemplate, QueryParser.parse(query), PreparedParams.empty(), plannerConfiguration, false, PlanHashable.PlanHashMode.VC0, query); @@ -318,21 +314,21 @@ private static void shouldFail(@Nonnull final String query, @Nonnull final Strin } } - private static void validateNotSameHash(@Nonnull final String query1, - @Nonnull final String query2) throws RelationalException { + private static void validateNotSameHash(final String query1, + final String query2) throws RelationalException { validateNotSameHash(query1, query2, PreparedParams.empty()); } - private static void validateNotSameHash(@Nonnull final String query1, - @Nonnull final String query2, - @Nonnull PreparedParams preparedParams) throws RelationalException { + private static void validateNotSameHash(final String query1, + final String query2, + PreparedParams preparedParams) throws RelationalException { validateNotSameHash(query1, preparedParams, query2, preparedParams); } - private static void validateNotSameHash(@Nonnull final String query1, - @Nonnull PreparedParams preparedParams1, - @Nonnull final String query2, - @Nonnull PreparedParams preparedParams2) throws RelationalException { + private static void validateNotSameHash(final String query1, + PreparedParams preparedParams1, + final String query2, + PreparedParams preparedParams2) throws RelationalException { final var result1 = AstNormalizer.normalizeAst(fakeSchemaTemplate, QueryParser.parse(query1), PreparedParams.copyOf(preparedParams1), plannerConfiguration, false, PlanHashable.PlanHashMode.VC0, query1); @@ -341,14 +337,14 @@ private static void validateNotSameHash(@Nonnull final String query1, Assertions.assertThat(result1.getQueryCacheKey().hashCode()).isNotEqualTo(result2.getQueryCacheKey().hashCode()); } - private static void validateNotEqual(@Nonnull final String query1, - @Nonnull final String query2) throws RelationalException { + private static void validateNotEqual(final String query1, + final String query2) throws RelationalException { validateNotEqual(query1, query2, PreparedParams.empty()); } - private static void validateNotEqual(@Nonnull final String query1, - @Nonnull final String query2, - @Nonnull PreparedParams preparedParams) throws RelationalException { + private static void validateNotEqual(final String query1, + final String query2, + PreparedParams preparedParams) throws RelationalException { final var result1 = AstNormalizer.normalizeAst(fakeSchemaTemplate, QueryParser.parse(query1), PreparedParams.copyOf(preparedParams), plannerConfiguration, false, PlanHashable.PlanHashMode.VC0, query1); final var result2 = AstNormalizer.normalizeAst(fakeSchemaTemplate, QueryParser.parse(query2), @@ -356,11 +352,11 @@ private static void validateNotEqual(@Nonnull final String query1, Assertions.assertThat(result1.getQueryCacheKey()).isNotEqualTo(result2.getQueryCacheKey()); } - private static void validateNotEqual(@Nonnull final String query1, - @Nonnull final RecordLayerSchemaTemplate schemaTemplate1, - @Nonnull final String query2, - @Nonnull final RecordLayerSchemaTemplate schemaTemplate2, - @Nonnull PreparedParams preparedParams) throws RelationalException { + private static void validateNotEqual(final String query1, + final RecordLayerSchemaTemplate schemaTemplate1, + final String query2, + final RecordLayerSchemaTemplate schemaTemplate2, + PreparedParams preparedParams) throws RelationalException { final var result1 = AstNormalizer.normalizeAst(schemaTemplate1, QueryParser.parse(query1), PreparedParams.copyOf(preparedParams), plannerConfiguration, false, PlanHashable.PlanHashMode.VC0, query1); final var result2 = AstNormalizer.normalizeAst(schemaTemplate2, QueryParser.parse(query2), @@ -369,7 +365,7 @@ private static void validateNotEqual(@Nonnull final String query1, } @SuppressWarnings("unchecked") - private static void compareBindings(@Nonnull final Object actual, @Nonnull final Object expected) { + private static void compareBindings(final Object actual, final Object expected) { Assertions.assertThat(actual instanceof Map).isTrue(); Assertions.assertThat(expected instanceof Map).isTrue(); final var actualMap = (Map) actual; @@ -383,15 +379,13 @@ private static void compareBindings(@Nonnull final Object actual, @Nonnull final } } - @Nonnull private static java.sql.Array toArrayParameter(List elements) throws SQLException { return EmbeddedRelationalArray.newBuilder().addAll(elements.toArray()).build(); } - @Nonnull - private static RecordLayerSchemaTemplate schemaTemplateWithFunction(@Nonnull final RecordLayerSchemaTemplate schemaTemplate, - @Nonnull final String name, - @Nonnull final String functionDdl, + private static RecordLayerSchemaTemplate schemaTemplateWithFunction(final RecordLayerSchemaTemplate schemaTemplate, + final String name, + final String functionDdl, boolean isTemporary) throws RelationalException { final String canonicalFunctionDdl; if (isTemporary) { @@ -411,15 +405,13 @@ private static RecordLayerSchemaTemplate schemaTemplateWithFunction(@Nonnull fin // invoking the compiled routine should only happen during plan generation. .withUserDefinedFunctionProvider(ignored -> new CompiledSqlFunction("", List.of(), List.of(), List.of(), Optional.empty(), null, Literals.empty()) { - @Nonnull @Override public RecordMetaDataProto.PUserDefinedFunction toProto() { throw new UnsupportedOperationException("unexpected call"); } - @Nonnull @Override - public RelationalExpression encapsulate(@Nonnull final CallSiteArguments arguments) { + public RelationalExpression encapsulate(final CallSiteArguments arguments) { throw new UnsupportedOperationException("unexpected call"); } }) @@ -674,7 +666,7 @@ void parseInPredicateWithConstantExpressionsNoConstantFolding() throws Exception "select * from t1 where col1 not in (10, null)", "select * from t1 where col1 in (10, col2, null)" }) - void parseInPredicateRejectsNull(@Nonnull final String query) { + void parseInPredicateRejectsNull(final String query) { Assertions.assertThatThrownBy(() -> validate(query, "unreachable", Map.of())) .isInstanceOf(UncheckedRelationalException.class) .hasMessageContaining("NULL values are not allowed in the IN list"); @@ -1617,8 +1609,7 @@ void windowFunctionOptionsAreNotStripped() throws Exception { Map.of(constantId(22), 10)); } - @Nonnull - private String normalizeQuery(@Nonnull final String functionDdl) throws RelationalException { + private String normalizeQuery(final String functionDdl) throws RelationalException { final var normalizer = AstNormalizer.normalizeAst(fakeSchemaTemplate, QueryParser.parse(functionDdl), PreparedParams.empty(), plannerConfiguration, false, PlanHashable.PlanHashMode.VC0, functionDdl); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/CaseSensitivityQueryTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/CaseSensitivityQueryTests.java index 4dd9c73f721..1a053215dc2 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/CaseSensitivityQueryTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/CaseSensitivityQueryTests.java @@ -31,8 +31,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; - -import javax.annotation.Nonnull; import java.net.URI; import java.sql.SQLException; @@ -142,7 +140,7 @@ void caseSensitiveConnectionTestCase3(boolean isCaseSensitive) throws Exception } } - private static void verifyResultSet(@Nonnull final RelationalResultSet resultSet) throws SQLException { + private static void verifyResultSet(final RelationalResultSet resultSet) throws SQLException { Assertions.assertTrue(resultSet.next()); Assertions.assertEquals(1, resultSet.getLong(1)); Assertions.assertEquals("bla", resultSet.getString(2)); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/DelegatingVisitorTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/DelegatingVisitorTest.java index 11bb4624234..a94e9a6484b 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/DelegatingVisitorTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/DelegatingVisitorTest.java @@ -41,8 +41,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.Mockito; - -import javax.annotation.Nonnull; import java.net.URI; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.BiConsumer; @@ -62,7 +60,6 @@ */ public class DelegatingVisitorTest { - @Nonnull private static RecordLayerSchemaTemplate generateMetadata() { return RecordLayerSchemaTemplate .newBuilder() @@ -130,9 +127,8 @@ void visitPredicatedExpressionTest() { (visitor, ctx) -> visitor.visitPredicatedExpression((RelationalParser.PredicatedExpressionContext) ctx), called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { - @Nonnull @Override - public Expression visitPredicatedExpression(@Nonnull RelationalParser.PredicatedExpressionContext ctx) { + public Expression visitPredicatedExpression(RelationalParser.PredicatedExpressionContext ctx) { called.set(true); return Expression.ofUnnamed(LiteralValue.ofScalar(42)); } @@ -147,7 +143,7 @@ void visitSubscriptExpressionTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override - public Expression visitSubscriptExpression(@Nonnull RelationalParser.SubscriptExpressionContext ctx) { + public Expression visitSubscriptExpression(RelationalParser.SubscriptExpressionContext ctx) { called.set(true); return Expression.ofUnnamed(LiteralValue.ofScalar(42)); } @@ -160,9 +156,8 @@ void visitUserDefinedMacroFunctionStatementBodyTest() { final AtomicBoolean called = new AtomicBoolean(false); final var visitor = new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, query, query, 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { - @Nonnull @Override - public Expression visitUserDefinedMacroFunctionStatementBody(@Nonnull RelationalParser.UserDefinedMacroFunctionStatementBodyContext ctx) { + public Expression visitUserDefinedMacroFunctionStatementBody(RelationalParser.UserDefinedMacroFunctionStatementBodyContext ctx) { called.set(true); return Expression.ofUnnamed(LiteralValue.ofScalar(42)); } @@ -183,9 +178,8 @@ void visitUserDefinedScalarFunctionNameTest() { (visitor, ctx) -> Assertions.assertThat(visitor.visitUserDefinedScalarFunctionName(ctx)).isEqualTo("testFunction"), called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { - @Nonnull @Override - public String visitUserDefinedScalarFunctionName(@Nonnull RelationalParser.UserDefinedScalarFunctionNameContext ctx) { + public String visitUserDefinedScalarFunctionName(RelationalParser.UserDefinedScalarFunctionNameContext ctx) { called.set(true); return "testFunction"; } @@ -281,9 +275,8 @@ void visitUserDefinedScalarFunctionCallTest() { (visitor, ctx) -> visitor.visitUserDefinedScalarFunctionCall((RelationalParser.UserDefinedScalarFunctionCallContext) ctx), called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { - @Nonnull @Override - public Expression visitUserDefinedScalarFunctionCall(@Nonnull RelationalParser.UserDefinedScalarFunctionCallContext ctx) { + public Expression visitUserDefinedScalarFunctionCall(RelationalParser.UserDefinedScalarFunctionCallContext ctx) { called.set(true); return Expression.ofUnnamed(LiteralValue.ofScalar(42)); } @@ -298,7 +291,7 @@ void visitIndexOptionsTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override - public Object visitIndexOptions(@Nonnull RelationalParser.IndexOptionsContext ctx) { + public Object visitIndexOptions(RelationalParser.IndexOptionsContext ctx) { called.set(true); return null; } @@ -313,7 +306,7 @@ void visitIndexOptionTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override - public Object visitIndexOption(@Nonnull RelationalParser.IndexOptionContext ctx) { + public Object visitIndexOption(RelationalParser.IndexOptionContext ctx) { called.set(true); return null; } @@ -328,7 +321,7 @@ void visitStatementOptionsTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override - public Object visitStatementOptions(@Nonnull RelationalParser.StatementOptionsContext ctx) { + public Object visitStatementOptions(RelationalParser.StatementOptionsContext ctx) { called.set(true); return null; } @@ -343,7 +336,7 @@ void visitStatementOptionTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override - public Object visitStatementOption(@Nonnull RelationalParser.StatementOptionContext ctx) { + public Object visitStatementOption(RelationalParser.StatementOptionContext ctx) { called.set(true); return null; } @@ -363,7 +356,7 @@ void visitVectorIndexDefinitionTest() { generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override @SuppressWarnings({"NullableProblems", "DataFlowIssue"}) - public RecordLayerIndex visitVectorIndexDefinition(@Nonnull RelationalParser.VectorIndexDefinitionContext ctx) { + public RecordLayerIndex visitVectorIndexDefinition(RelationalParser.VectorIndexDefinitionContext ctx) { called.set(true); return null; } @@ -381,7 +374,6 @@ void visitPartitionClauseTest() { }, called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, query, query, 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { - @Nonnull @Override public Expressions visitPartitionClause(final RelationalParser.PartitionClauseContext ctx) { called.set(true); @@ -399,7 +391,7 @@ void visitIndexColumnListTest() { generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override @SuppressWarnings({"NullableProblems", "DataFlowIssue"}) - public Object visitIndexColumnList(@Nonnull RelationalParser.IndexColumnListContext ctx) { + public Object visitIndexColumnList(RelationalParser.IndexColumnListContext ctx) { called.set(true); return null; } @@ -415,7 +407,7 @@ void visitIncludeClauseTest() { generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override @SuppressWarnings({"NullableProblems", "DataFlowIssue"}) - public Object visitIncludeClause(@Nonnull RelationalParser.IncludeClauseContext ctx) { + public Object visitIncludeClause(RelationalParser.IncludeClauseContext ctx) { called.set(true); return null; } @@ -435,7 +427,7 @@ void visitIndexOnSourceDefinitionTest() { generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override @SuppressWarnings({"NullableProblems", "DataFlowIssue"}) - public RecordLayerIndex visitIndexOnSourceDefinition(@Nonnull RelationalParser.IndexOnSourceDefinitionContext ctx) { + public RecordLayerIndex visitIndexOnSourceDefinition(RelationalParser.IndexOnSourceDefinitionContext ctx) { called.set(true); return null; } @@ -450,7 +442,7 @@ void visitIndexTypeTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override - public Object visitIndexType(@Nonnull RelationalParser.IndexTypeContext ctx) { + public Object visitIndexType(RelationalParser.IndexTypeContext ctx) { called.set(true); return null; } @@ -466,7 +458,7 @@ void visitIndexColumnSpecTest() { generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override @SuppressWarnings({"NullableProblems", "DataFlowIssue"}) - public Object visitIndexColumnSpec(@Nonnull RelationalParser.IndexColumnSpecContext ctx) { + public Object visitIndexColumnSpec(RelationalParser.IndexColumnSpecContext ctx) { called.set(true); return null; } @@ -486,7 +478,7 @@ void visitIndexAsSelectDefinitionTest() { generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override @SuppressWarnings({"NullableProblems", "DataFlowIssue"}) - public RecordLayerIndex visitIndexAsSelectDefinition(@Nonnull RelationalParser.IndexAsSelectDefinitionContext ctx) { + public RecordLayerIndex visitIndexAsSelectDefinition(RelationalParser.IndexAsSelectDefinitionContext ctx) { called.set(true); return null; } @@ -501,7 +493,7 @@ void visitOrderClauseTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override - public Object visitOrderClause(@Nonnull RelationalParser.OrderClauseContext ctx) { + public Object visitOrderClause(RelationalParser.OrderClauseContext ctx) { called.set(true); return null; } @@ -516,7 +508,7 @@ void visitVectorIndexOptionsTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override - public Object visitVectorIndexOptions(@Nonnull RelationalParser.VectorIndexOptionsContext ctx) { + public Object visitVectorIndexOptions(RelationalParser.VectorIndexOptionsContext ctx) { called.set(true); return null; } @@ -531,7 +523,7 @@ void visitHnswMetricTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override - public Object visitHnswMetric(@Nonnull RelationalParser.HnswMetricContext ctx) { + public Object visitHnswMetric(RelationalParser.HnswMetricContext ctx) { called.set(true); return null; } @@ -546,7 +538,7 @@ void visitVectorEngineTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override - public Object visitVectorEngine(@Nonnull RelationalParser.VectorEngineContext ctx) { + public Object visitVectorEngine(RelationalParser.VectorEngineContext ctx) { called.set(true); return null; } @@ -561,7 +553,7 @@ void visitVectorIndexOptionValueTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override - public Object visitVectorIndexOptionValue(@Nonnull RelationalParser.VectorIndexOptionValueContext ctx) { + public Object visitVectorIndexOptionValue(RelationalParser.VectorIndexOptionValueContext ctx) { called.set(true); return null; } @@ -576,7 +568,7 @@ void visitVectorIndexOptionTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override - public Object visitVectorIndexOption(@Nonnull RelationalParser.VectorIndexOptionContext ctx) { + public Object visitVectorIndexOption(RelationalParser.VectorIndexOptionContext ctx) { called.set(true); return null; } @@ -591,7 +583,7 @@ void visitIndexPartitionClauseTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override - public Object visitIndexPartitionClause(@Nonnull RelationalParser.IndexPartitionClauseContext ctx) { + public Object visitIndexPartitionClause(RelationalParser.IndexPartitionClauseContext ctx) { called.set(true); return null; } @@ -605,9 +597,8 @@ void visitWindowOptionsClauseTest() { DelegatingVisitor::visitWindowOptionsClause, called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { - @Nonnull @Override - public Expressions visitWindowOptionsClause(@Nonnull RelationalParser.WindowOptionsClauseContext ctx) { + public Expressions visitWindowOptionsClause(RelationalParser.WindowOptionsClauseContext ctx) { called.set(true); return null; } @@ -621,9 +612,8 @@ void visitWindowOptionTest() { DelegatingVisitor::visitWindowOption, called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { - @Nonnull @Override - public Expression visitWindowOption(@Nonnull RelationalParser.WindowOptionContext ctx) { + public Expression visitWindowOption(RelationalParser.WindowOptionContext ctx) { called.set(true); return null; } @@ -638,7 +628,7 @@ void visitWindowSpecTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override - public Object visitWindowSpec(@Nonnull RelationalParser.WindowSpecContext ctx) { + public Object visitWindowSpec(RelationalParser.WindowSpecContext ctx) { called.set(true); return null; } @@ -652,9 +642,8 @@ void visitNonAggregateFunctionCallTest() { (visitor, ctx) -> visitor.visitNonAggregateFunctionCall((RelationalParser.NonAggregateFunctionCallContext) ctx), called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { - @Nonnull @Override - public Expression visitNonAggregateFunctionCall(@Nonnull RelationalParser.NonAggregateFunctionCallContext ctx) { + public Expression visitNonAggregateFunctionCall(RelationalParser.NonAggregateFunctionCallContext ctx) { called.set(true); return Expression.ofUnnamed(LiteralValue.ofScalar(42)); } @@ -671,9 +660,8 @@ void visitNullTreatmentClauseTest() { (visitor, ctx) -> Assertions.assertThat(visitor.visitNullTreatmentClause(ctx)).isTrue(), called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { - @Nonnull @Override - public Boolean visitNullTreatmentClause(@Nonnull RelationalParser.NullTreatmentClauseContext ctx) { + public Boolean visitNullTreatmentClause(RelationalParser.NullTreatmentClauseContext ctx) { called.set(true); return ctx.nullTreatment.getType() == RelationalParser.IGNORE; } @@ -690,9 +678,8 @@ void visitFunctionNameKeywordTest() { DelegatingVisitor::visitFunctionNameKeyword, called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { - @Nonnull @Override - public Object visitFunctionNameKeyword(@Nonnull RelationalParser.FunctionNameKeywordContext ctx) { + public Object visitFunctionNameKeyword(RelationalParser.FunctionNameKeywordContext ctx) { called.set(true); return null; } @@ -748,9 +735,8 @@ void visitNamedOrUnnamedFunctionArgs() { final AtomicBoolean called = new AtomicBoolean(false); final var visitor = new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, query, query, 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { - @Nonnull @Override - public Expressions visitNamedOrUnnamedFunctionArgs(@Nonnull RelationalParser.NamedOrUnnamedFunctionArgsContext context) { + public Expressions visitNamedOrUnnamedFunctionArgs(RelationalParser.NamedOrUnnamedFunctionArgsContext context) { called.set(true); return Expressions.ofSingle(Expression.ofUnnamed(LiteralValue.ofScalar(42))); } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/ExpressionTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/ExpressionTests.java index b9ca0e58a99..52911db031c 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/ExpressionTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/ExpressionTests.java @@ -46,8 +46,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; - -import javax.annotation.Nonnull; import java.util.List; import java.util.Optional; import java.util.stream.Stream; @@ -61,9 +59,7 @@ class ExpressionTests { Type.Record.Field.of(Type.primitiveType(Type.TypeCode.STRING, false), Optional.of("b"), Optional.of(2)) )); - @Nonnull private static final Expression ANONYMOUS = new Expression(Optional.empty(), DataType.StringType.notNullable(), LiteralValue.ofScalar("hello")); - @Nonnull private static final Expression FOO = new Expression(Optional.of(Identifier.of("foo")), DataType.LongType.notNullable(), LiteralValue.ofScalar(42L)); @BeforeAll @@ -80,8 +76,7 @@ static void tearDownDebugger() { Debugger.setDebugger(null); } - @Nonnull - private static Expression createEphemeral(@Nonnull Expression expression) { + private static Expression createEphemeral(Expression expression) { final Expression ephemeral = expression.asEphemeral(); try (AutoCloseableSoftAssertions softly = new AutoCloseableSoftAssertions()) { softly.assertThat(ephemeral) @@ -98,7 +93,6 @@ private static Expression createEphemeral(@Nonnull Expression expression) { return ephemeral; } - @Nonnull static Stream expressions() { // Construct the bar expression in this method as it references a quantifier, and we want the quantifier // unique ID to use the debugger, and so we want it to construct a new one with each invocation @@ -107,7 +101,6 @@ static Stream expressions() { .flatMap(expr -> expr.getName().isPresent() ? Stream.of(expr, createEphemeral(expr)) : Stream.of(expr)); } - @Nonnull static Stream withName() { final List names = List.of("blah", "foo", "bar"); return expressions().flatMap(expr -> @@ -116,7 +109,7 @@ static Stream withName() { @ParameterizedTest @MethodSource - void withName(@Nonnull Expression originalExpression, @Nonnull Identifier newName) { + void withName(Expression originalExpression, Identifier newName) { final Expression newExpression = originalExpression.withName(newName); try (AutoCloseableSoftAssertions softly = new AutoCloseableSoftAssertions()) { if (originalExpression.getName().isPresent() && originalExpression.getName().get().equals(newName)) { @@ -144,13 +137,12 @@ void withName(@Nonnull Expression originalExpression, @Nonnull Identifier newNam } } - @Nonnull static Stream withUnderlying() { return expressions().flatMap(expr -> Stream.of(Arguments.of(expr, expr.getUnderlying()), Arguments.of(expr, QuantifiedObjectValue.of(Quantifier.current(), expr.getUnderlying().getResultType())))); } - private static boolean dataTypesEqualIgnoringStructName(@Nonnull DataType type1, @Nonnull DataType type2) { + private static boolean dataTypesEqualIgnoringStructName(DataType type1, DataType type2) { if (type1 instanceof DataType.StructType && type2 instanceof DataType.StructType) { final DataType.StructType structType1 = (DataType.StructType) type1; final DataType.StructType structType2 = (DataType.StructType) type2; @@ -176,7 +168,7 @@ private static boolean dataTypesEqualIgnoringStructName(@Nonnull DataType type1, @ParameterizedTest @MethodSource - void withUnderlying(@Nonnull Expression originalExpression, @Nonnull Value newUnderlying) { + void withUnderlying(Expression originalExpression, Value newUnderlying) { final Expression newExpression = originalExpression.withUnderlying(newUnderlying); try (AutoCloseableSoftAssertions softly = new AutoCloseableSoftAssertions()) { if (originalExpression.getUnderlying().semanticEquals(newUnderlying, AliasMap.emptyMap())) { @@ -207,7 +199,6 @@ void withUnderlying(@Nonnull Expression originalExpression, @Nonnull Value newUn } } - @Nonnull static Stream modifyQualifier() { return expressions().flatMap(expr -> Stream.of( @@ -243,7 +234,6 @@ void modifyQualifier(final Expression expression, Expression qualified) { } } - @Nonnull private static Stream clearQualifier() { return expressions().flatMap(expr -> Stream.of( @@ -254,17 +244,17 @@ private static Stream clearQualifier() { @ParameterizedTest @MethodSource - void clearQualifier(@Nonnull Expression expression) { + void clearQualifier(Expression expression) { assertQualifierIsCleared(expression, expression.clearQualifier()); } @ParameterizedTest @MethodSource("clearQualifier") - void clearQualifierViaWithEmptyQualifier(@Nonnull Expression expression) { + void clearQualifierViaWithEmptyQualifier(Expression expression) { assertQualifierIsCleared(expression, expression.withQualifier(Optional.empty())); } - private void assertQualifierIsCleared(@Nonnull Expression expression, @Nonnull Expression withClearedQualifier) { + private void assertQualifierIsCleared(Expression expression, Expression withClearedQualifier) { try (AutoCloseableSoftAssertions softly = new AutoCloseableSoftAssertions()) { if (expression.getName().isEmpty()) { softly.assertThat(withClearedQualifier) @@ -293,14 +283,12 @@ private void assertQualifierIsCleared(@Nonnull Expression expression, @Nonnull E } } - @Nonnull - private static Stream variantsForPullUp(@Nonnull Expression expression) { + private static Stream variantsForPullUp(Expression expression) { final Expression withName1 = expression.withName(Identifier.of("blah")); final Expression withName2 = expression.withName(Identifier.of("blah", ImmutableList.of("qualifier"))); return Stream.of(expression, withName1, withName1.asEphemeral(), withName2, withName2.asEphemeral()); } - @Nonnull static Stream pullUp() { // Start with an expression on a field value, then pull it through an RCV final Value lower = QuantifiedObjectValue.of(CorrelationIdentifier.uniqueId(), REC_TYPE); @@ -321,7 +309,7 @@ static Stream pullUp() { @ParameterizedTest @MethodSource - void pullUp(final Expression expression, @Nonnull Value toPullThrough, @Nonnull CorrelationIdentifier newId, @Nonnull Value pulledThrough) { + void pullUp(final Expression expression, Value toPullThrough, CorrelationIdentifier newId, Value pulledThrough) { final Expression newExpression = expression.pullUp(toPullThrough, newId, ImmutableSet.of()); try (AutoCloseableSoftAssertions softly = new AutoCloseableSoftAssertions()) { @@ -344,7 +332,6 @@ void pullUp(final Expression expression, @Nonnull Value toPullThrough, @Nonnull } } - @Nonnull static Stream namedArgumentExpressionCreateNew() { final Expression.NamedArgumentExpression namedArg = FOO.toNamedArgument(); final Identifier newName = Identifier.of("newName"); @@ -361,7 +348,7 @@ static Stream namedArgumentExpressionCreateNew() { @ParameterizedTest @MethodSource - void namedArgumentExpressionCreateNew(@Nonnull Expression result) { + void namedArgumentExpressionCreateNew(Expression result) { try (AutoCloseableSoftAssertions softly = new AutoCloseableSoftAssertions()) { softly.assertThat(result) .isInstanceOf(Expression.NamedArgumentExpression.class) @@ -369,7 +356,6 @@ void namedArgumentExpressionCreateNew(@Nonnull Expression result) { } } - @Nonnull static Stream toNamedArgument() { return Stream.of( Arguments.of(FOO, Identifier.of("id")), @@ -380,7 +366,7 @@ static Stream toNamedArgument() { @ParameterizedTest @MethodSource - void toNamedArgument(@Nonnull Expression expression, @Nonnull Identifier argumentName) { + void toNamedArgument(Expression expression, Identifier argumentName) { final Expression.NamedArgumentExpression namedArg = expression.toNamedArgument(argumentName); try (AutoCloseableSoftAssertions softly = new AutoCloseableSoftAssertions()) { diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/LiteralsTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/LiteralsTests.java index e29f1f7e53e..8520a3501e3 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/LiteralsTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/LiteralsTests.java @@ -26,8 +26,6 @@ import com.google.common.collect.ImmutableSet; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; - -import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -41,7 +39,6 @@ */ public class LiteralsTests { - @Nonnull private final Random random = new Random(42L); @Test @@ -79,20 +76,17 @@ void nullLiteralsAreNotExcluded() { Assertions.assertEquals(expectedMap, actualAsMap); } - @Nonnull private static OrderedLiteral nonNullLiteral(int tokenIndex, int value) { return new OrderedLiteral(Type.primitiveType(Type.TypeCode.LONG), value, null, null, tokenIndex, Optional.empty()); } - @Nonnull private static OrderedLiteral nullLiteral(int tokenIndex) { return new OrderedLiteral(Type.primitiveType(Type.TypeCode.NULL), null /*literal value*/, null, null, tokenIndex, Optional.empty()); } private static final int ARGUMENTS_SIZE = 100; - @Nonnull - public static Set generateUniqueIntegers(@Nonnull final Random random, int min, int max, int count) { + public static Set generateUniqueIntegers(final Random random, int min, int max, int count) { Assert.thatUnchecked(0 <= min && min < max, "invalid range boundaries"); Assert.thatUnchecked(count > 0 && count <= (max - min), "pick values' range is smaller than the desired number of unique values"); return random.ints(min, max + 1) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/QueryTestUtils.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/QueryTestUtils.java index 5535aa2bbd1..65cf5f9a393 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/QueryTestUtils.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/QueryTestUtils.java @@ -25,13 +25,11 @@ import com.apple.foundationdb.relational.api.RelationalStruct; import org.junit.jupiter.api.Assertions; - -import javax.annotation.Nonnull; import java.sql.SQLException; public class QueryTestUtils { - public static RelationalStruct insertT1Record(@Nonnull final RelationalStatement statement, long pk, long a, long b, long c) throws SQLException { + public static RelationalStruct insertT1Record(final RelationalStatement statement, long pk, long a, long b, long c) throws SQLException { var result = EmbeddedRelationalStruct.newBuilder() .addLong("PK", pk) .addLong("A", a) @@ -43,7 +41,7 @@ public static RelationalStruct insertT1Record(@Nonnull final RelationalStatement return result; } - public static RelationalStruct insertT1RecordColAIsNull(@Nonnull final RelationalStatement statement, long pk, long b, long c) throws SQLException { + public static RelationalStruct insertT1RecordColAIsNull(final RelationalStatement statement, long pk, long b, long c) throws SQLException { var result = EmbeddedRelationalStruct.newBuilder() .addLong("PK", pk) .addLong("B", b) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/QueryTypeTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/QueryTypeTests.java index c410c5c714e..3215b7ce977 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/QueryTypeTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/QueryTypeTests.java @@ -30,8 +30,6 @@ import org.junit.jupiter.params.provider.ArgumentsProvider; import org.junit.jupiter.params.provider.ArgumentsSource; import org.junit.jupiter.params.support.ParameterDeclarations; - -import javax.annotation.Nonnull; import java.util.stream.Stream; /** @@ -65,7 +63,7 @@ public Stream provideArguments(final ParameterDeclarations @ParameterizedTest(name = "{0} IS {1}") @ArgumentsSource(QueriesProvider.class) - public void queryTypeIsSetCorrectly(@Nonnull final String query, @Nonnull ParseTreeInfo.QueryType expectedType) throws Exception { + public void queryTypeIsSetCorrectly(final String query, ParseTreeInfo.QueryType expectedType) throws Exception { final var parseInfo = QueryParser.parse(query); Assertions.assertEquals(expectedType, parseInfo.getQueryType()); } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/StandardQueryTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/StandardQueryTests.java index 48e0819b0cf..14b143bafe6 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/StandardQueryTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/StandardQueryTests.java @@ -55,9 +55,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.net.URI; import java.nio.charset.StandardCharsets; import java.sql.Array; @@ -80,9 +78,8 @@ public class StandardQueryTests { /** * A restaurant review. */ - private record Review(long reviewer, long rating, @Nonnull List> endorsements) { - @Nonnull - static Review of(long reviewer, long rating, @Nonnull final List> endorsements) { + private record Review(long reviewer, long rating, List> endorsements) { + static Review of(long reviewer, long rating, final List> endorsements) { return new Review(reviewer, rating, endorsements); } } @@ -1627,7 +1624,6 @@ void testInsertStructWithUuidTest() throws Exception { } } - @Nonnull private static Stream vectorTypeProvider() { return Stream.of( Arguments.of("vector(3, half)", new HalfRealVector(new double[]{1.1d, 1.2d, 1.3d})), @@ -1723,11 +1719,11 @@ private RelationalStruct insertRestaurantComplexRecord(RelationalStatement s, Lo return insertRestaurantComplexRecord(s, recordNumber, "testName"); } - private RelationalStruct insertRestaurantComplexRecord(RelationalStatement s, Long recordNumber, @Nonnull final String recordName) throws SQLException { + private RelationalStruct insertRestaurantComplexRecord(RelationalStatement s, Long recordNumber, final String recordName) throws SQLException { return insertRestaurantComplexRecord(s, recordNumber, recordName, List.of()); } - private RelationalStruct insertRestaurantComplexRecord(RelationalStatement s, Long recordNumber, @Nonnull final String recordName, @Nonnull final List reviews) throws SQLException { + private RelationalStruct insertRestaurantComplexRecord(RelationalStatement s, Long recordNumber, final String recordName, final List reviews) throws SQLException { final var recBuilder2 = EmbeddedRelationalStruct.newBuilder() .addLong("REST_NO", recordNumber) .addString("NAME", recordName) @@ -1758,7 +1754,7 @@ private RelationalStruct insertRestaurantComplexRecord(RelationalStatement s, Lo return getExpected(recordNumber, recordName, reviews); } - private static RelationalStruct getExpected(Long recordNumber, @Nonnull final String recordName, @Nonnull final List reviews) { + private static RelationalStruct getExpected(Long recordNumber, final String recordName, final List reviews) { final var locationType = DataType.StructType.from("LOCATION", List.of( DataType.StructType.Field.from("ADDRESS", DataType.Primitives.STRING.type(), 1), DataType.StructType.Field.from("LATITUDE", DataType.Primitives.STRING.type(), 2), @@ -1795,7 +1791,7 @@ private static RelationalStruct getExpected(Long recordNumber, @Nonnull final St return new ImmutableRowStruct(new ArrayRow(recordNumber, recordName, locationStruct, reviewsArray), RelationalStructMetaData.of(restaurantComplexRecordType)); } - private void insertRestaurantComplexRecord(RelationalStatement s, int recordNumber, @Nonnull final String recordName, byte[] blob) throws SQLException { + private void insertRestaurantComplexRecord(RelationalStatement s, int recordNumber, final String recordName, byte[] blob) throws SQLException { var struct = EmbeddedRelationalStruct.newBuilder() .addLong("REST_NO", recordNumber) .addString("NAME", recordName) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/TemporaryFunctionTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/TemporaryFunctionTests.java index 8ddfbbdedec..22977f36d08 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/TemporaryFunctionTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/TemporaryFunctionTests.java @@ -61,8 +61,6 @@ import org.junit.jupiter.params.provider.ValueSource; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; - -import javax.annotation.Nonnull; import java.net.URI; import java.sql.SQLException; import java.util.Optional; @@ -264,7 +262,7 @@ void temporaryFunctionIsMemoizedAcrossInvocations() throws Exception { } } - private UserDefinedFunction getUserDefinedFunction(@Nonnull RelationalConnection connection, @Nonnull String name) throws RelationalException { + private UserDefinedFunction getUserDefinedFunction(RelationalConnection connection, String name) throws RelationalException { final var boundSchemaTemplateMaybe = ((EmbeddedRelationalConnection) connection).getTransaction().getBoundSchemaTemplateMaybe(); Assertions.assertTrue(boundSchemaTemplateMaybe.isPresent()); final var invokedRoutineMaybe = boundSchemaTemplateMaybe.get().findInvokedRoutineByName(name); @@ -1124,9 +1122,8 @@ void createTemporaryFunctionDoNotParseBodyPreemptively() throws Exception { .setName("FOO").build()).build(); final var called = new AtomicBoolean(false); final var metadataOperationsFactory = new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getCreateTemporaryFunctionConstantAction(@Nonnull final SchemaTemplate template, final boolean throwIfExists, @Nonnull final RecordLayerInvokedRoutine invokedRoutine) { + public ConstantAction getCreateTemporaryFunctionConstantAction(final SchemaTemplate template, final boolean throwIfExists, final RecordLayerInvokedRoutine invokedRoutine) { return new CreateTemporaryFunctionConstantAction(template, throwIfExists, invokedRoutine); } }; diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/TransactionBoundQueryTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/TransactionBoundQueryTest.java index d430de7b520..87ba3956df6 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/TransactionBoundQueryTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/TransactionBoundQueryTest.java @@ -61,8 +61,6 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; - -import javax.annotation.Nonnull; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; @@ -71,7 +69,6 @@ import java.util.stream.Stream; public class TransactionBoundQueryTest { - @Nonnull private static final String SCHEMA_TEMPLATE = """ CREATE TABLE t1(id bigint, a bigint, b string, PRIMARY KEY(id)) @@ -81,13 +78,11 @@ CREATE TABLE t3(id bigint, a bigint, e bigint, f bigint, PRIMARY KEY(id)) """; @RegisterExtension @Order(0) - @Nonnull final EmbeddedRelationalExtension embeddedExtension = new EmbeddedRelationalExtension(); @RegisterExtension @Order(1) final SimpleDatabaseRule databaseRule = new SimpleDatabaseRule(TransactionBoundQueryTest.class, SCHEMA_TEMPLATE); - @Nonnull private static Options engineOptions() throws SQLException { return Options.builder() .withOption(Options.Name.PLAN_CACHE_PRIMARY_MAX_ENTRIES, 100) @@ -96,14 +91,12 @@ private static Options engineOptions() throws SQLException { .build(); } - @Nonnull private EmbeddedRelationalConnection connectEmbedded() throws SQLException { Connection connection = DriverManager.getConnection(databaseRule.getConnectionUri().toString()); connection.setSchema(databaseRule.getSchemaName()); return connection.unwrap(EmbeddedRelationalConnection.class); } - @Nonnull private FDBRecordContext openContext() throws SQLException, RelationalException { try (EmbeddedRelationalConnection connection = connectEmbedded()) { connection.createNewTransaction(); @@ -115,8 +108,7 @@ private FDBRecordContext openContext() throws SQLException, RelationalException } } - @Nonnull - private EmbeddedRelationalConnection connectTransactionBound(@Nonnull FDBRecordContext context, @Nonnull RecordMetaData metaData) throws SQLException, RelationalException { + private EmbeddedRelationalConnection connectTransactionBound(FDBRecordContext context, RecordMetaData metaData) throws SQLException, RelationalException { try (EmbeddedRelationalConnection embeddedConnection = connectEmbedded()) { embeddedConnection.createNewTransaction(); AbstractDatabase db = embeddedConnection.getRecordLayerDatabase(); @@ -164,7 +156,7 @@ private void insertT3Data(EmbeddedRelationalConnection connection) throws SQLExc } } - private RecordMetaData getUpdatedMetaData(@Nonnull Consumer metaDataUpdater) throws SQLException, RelationalException { + private RecordMetaData getUpdatedMetaData(Consumer metaDataUpdater) throws SQLException, RelationalException { try (EmbeddedRelationalConnection connection = connectEmbedded()) { connection.createNewTransaction(); SchemaTemplate schemaTemplate = connection.getSchemaTemplate(); @@ -482,7 +474,6 @@ void countAndFilterOnAdditionIndex() throws SQLException, RelationalException { } } - @Nonnull static Stream countByAdditionGroupWithFilterOnOtherColumn() { return Stream.of("", " ORDER BY f - e ASC", " ORDER BY f - e DESC"); } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/ConcurrentCacheTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/ConcurrentCacheTests.java index 58f24b32078..4189c33e926 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/ConcurrentCacheTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/ConcurrentCacheTests.java @@ -32,9 +32,7 @@ import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.Map; import java.util.Optional; import java.util.Random; @@ -51,75 +49,65 @@ */ public class ConcurrentCacheTests { - @Nonnull private static final TypeRepository EMPTY_TYPE_REPO = TypeRepository.empty(); @Nullable - private static V pickFirst(@Nonnull final Stream stream) { + private static V pickFirst(final Stream stream) { return stream.findFirst().orElse(null); } - @Nonnull - private static PhysicalPlanEquivalence ppeFor(@Nonnull final QueryPlanConstraint constraint) { + private static PhysicalPlanEquivalence ppeFor(final QueryPlanConstraint constraint) { return new PhysicalPlanEquivalence(Optional.of(constraint), Optional.empty()); } - @Nonnull - private static PhysicalPlanEquivalence ppeFor(@Nonnull final EvaluationContext evaluationContext) { + private static PhysicalPlanEquivalence ppeFor(final EvaluationContext evaluationContext) { return new PhysicalPlanEquivalence(Optional.empty(), Optional.of(evaluationContext)); } - @Nonnull private static EvaluationContext ecFor(int value) { return EvaluationContext.newBuilder().setConstant(Quantifier.constant(), Map.of(constantId(0), value)).build(EMPTY_TYPE_REPO); } - @Nonnull private static final QueryPlanConstraint lt150Constraint = QueryPlanConstraint.ofPredicate( new ValuePredicate(ConstantObjectValue.of(Quantifier.constant(), constantId(0), Type.primitiveType(Type.TypeCode.INT)), new Comparisons.SimpleComparison(Comparisons.Type.LESS_THAN, 150))); - @Nonnull private static final QueryPlanConstraint lt500Constraint = QueryPlanConstraint.ofPredicate( new ValuePredicate(ConstantObjectValue.of(Quantifier.constant(), constantId(0), Type.primitiveType(Type.TypeCode.INT)), new Comparisons.SimpleComparison(Comparisons.Type.LESS_THAN, 500))); - @Nonnull private static final QueryPlanConstraint lt1000Constraint = QueryPlanConstraint.ofPredicate( new ValuePredicate(ConstantObjectValue.of(Quantifier.constant(), constantId(0), Type.primitiveType(Type.TypeCode.INT)), new Comparisons.SimpleComparison(Comparisons.Type.LESS_THAN, 1000))); - @Nonnull private static String generateFullScan() { return "full scan"; } - @Nonnull private static String generateIScan(int boundary) { return "full scan with " + boundary; } - private static void getOrLoadT1lt300(@Nonnull final MultiStageCache cache) { + private static void getOrLoadT1lt300(final MultiStageCache cache) { final var result = cache.reduce("T1", "1", ppeFor(ecFor(300)), () -> NonnullPair.of(ppeFor(lt500Constraint), generateIScan(500)), s -> s + " overriden with 300", ConcurrentCacheTests::pickFirst, NoOpMetricCollector.INSTANCE); Assertions.assertThat(result).doesNotContain("150"); // we must not scan index <150 as the returned results would be incorrect } - private static void getOrLoadT1lt90(@Nonnull final MultiStageCache cache) { + private static void getOrLoadT1lt90(final MultiStageCache cache) { cache.reduce("T1", "1", ppeFor(ecFor(90)), () -> NonnullPair.of(ppeFor(lt150Constraint), generateIScan(150)), s -> s + " overriden with 90", ConcurrentCacheTests::pickFirst, NoOpMetricCollector.INSTANCE); } - private static void getOrLoadT1lt1000(@Nonnull final MultiStageCache cache) { + private static void getOrLoadT1lt1000(final MultiStageCache cache) { final var result = cache.reduce("T1", "1", ppeFor(ecFor(1000)), () -> NonnullPair.of(ppeFor(lt1000Constraint), generateFullScan()), s -> s + " overriden with 1000", ConcurrentCacheTests::pickFirst, NoOpMetricCollector.INSTANCE); Assertions.assertThat(result).doesNotContain("150", "500"); // we must not scan index <150 or <500 as the returned results would be incorrect } - @Nonnull private static final Random random = new Random(); - private static void randomWorkLoad(@Nonnull final MultiStageCache cache) throws InterruptedException { + private static void randomWorkLoad(final MultiStageCache cache) throws InterruptedException { final Map>> actions = Map.of(0, ConcurrentCacheTests::getOrLoadT1lt1000, 1, ConcurrentCacheTests::getOrLoadT1lt300, 2, ConcurrentCacheTests::getOrLoadT1lt90); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/ConstraintValidityTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/ConstraintValidityTests.java index e57909c6e1c..935db1a1362 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/ConstraintValidityTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/ConstraintValidityTests.java @@ -56,8 +56,6 @@ import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; - -import javax.annotation.Nonnull; import java.util.AbstractMap; import java.util.Arrays; import java.util.HashMap; @@ -82,22 +80,16 @@ public class ConstraintValidityTests { public final RelationalConnectionRule connection = new RelationalConnectionRule(database::getConnectionUri) .withSchema("TEST_SCHEMA"); - @Nonnull private static final String MaxScoreByGame10 = "MAXSCOREBYGAME10"; - @Nonnull private static final String MaxScoreByGame20 = "MAXSCOREBYGAME20"; - @Nonnull private static final String BitAndScore2 = "BITANDSCORE2"; - @Nonnull private static final String BitAndScore4 = "BITANDSCORE4"; - @Nonnull private static final String GameIdx = "GAMEIDX"; - @Nonnull private static final String Scan = "SCAN"; @BeforeAll @@ -105,8 +97,7 @@ public static void beforeAll() { Utils.enableCascadesDebugger(); } - @Nonnull - private PlanGenerator getPlanGenerator(@Nonnull final RelationalPlanCache cache) throws Exception { + private PlanGenerator getPlanGenerator(final RelationalPlanCache cache) throws Exception { final var schemaName = connection.getSchema(); final var embeddedConnection = connection.getUnderlyingEmbeddedConnection().unwrap(EmbeddedRelationalConnection.class); final var readableIndexes = ImmutableSet.of(MaxScoreByGame10, MaxScoreByGame20, BitAndScore2, BitAndScore4); @@ -124,9 +115,9 @@ private PlanGenerator getPlanGenerator(@Nonnull final RelationalPlanCache cache) return PlanGenerator.create(Optional.of(cache), planContext, store.getRecordMetaData(), storeState, store.getIndexMaintainerRegistry(), Options.builder().build()); } - private void planQuery(@Nonnull final RelationalPlanCache cache, - @Nonnull final String query, - @Nonnull final String expectedPhysicalPlan) throws Exception { + private void planQuery(final RelationalPlanCache cache, + final String query, + final String expectedPhysicalPlan) throws Exception { connection.setAutoCommit(false); connection.getUnderlyingEmbeddedConnection().createNewTransaction(); final var planGenerator = getPlanGenerator(cache); @@ -136,8 +127,7 @@ private void planQuery(@Nonnull final RelationalPlanCache cache, Assertions.assertEquals(inferScanType(plan), expectedPhysicalPlan); } - @Nonnull - private RelationalPlanCache getCache(@Nonnull final FakeTicker ticker) { + private RelationalPlanCache getCache(final FakeTicker ticker) { return RelationalPlanCache.newRelationalCacheBuilder() .setExecutor(Runnable::run) .setSize(2) @@ -153,8 +143,7 @@ private RelationalPlanCache getCache(@Nonnull final FakeTicker ticker) { .build(); } - @Nonnull - private static String inferScanType(@Nonnull final Plan plan) { + private static String inferScanType(final Plan plan) { Assertions.assertInstanceOf(QueryPlan.PhysicalQueryPlan.class, plan); final var physicalPlan = (QueryPlan.PhysicalQueryPlan) plan; final var desc = physicalPlan.getRecordQueryPlan().toString(); // very ad-hoc :/ @@ -173,7 +162,6 @@ private static String inferScanType(@Nonnull final Plan plan) { } } - @Nonnull private static QueryPredicate ofTypeInt(final int tokenIndex) { return new ValuePredicate(OfTypeValue.of(ConstantObjectValue.of(Quantifier.constant(), constantId(tokenIndex), Type.primitiveType(Type.TypeCode.INT)), Type.primitiveType(Type.TypeCode.INT, false)), @@ -181,30 +169,25 @@ private static QueryPredicate ofTypeInt(final int tokenIndex) { } @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - @Nonnull private static QueryPredicate isNotNull(final int tokenIndex, final Optional scope, Type type) { return new ValuePredicate(EvaluatesToValue.isNotNull( ConstantObjectValue.of(Quantifier.constant(), constantId(tokenIndex, scope), type)), new Comparisons.SimpleComparison(Comparisons.Type.EQUALS, true)); } - @Nonnull private static QueryPredicate isNotNullInt(final int tokenIndex) { return isNotNull(tokenIndex, Optional.empty(), Type.primitiveType(Type.TypeCode.INT)); } - @Nonnull - private static QueryPredicate and(@Nonnull final QueryPredicate... predicates) { + private static QueryPredicate and(final QueryPredicate... predicates) { return AndPredicate.and(Arrays.asList(predicates)); } - @Nonnull private static QueryPredicate equalsConstraint(int tokenIndex, int value) { return new ValuePredicate(ConstantObjectValue.of(Quantifier.constant(), constantId(tokenIndex), Type.primitiveType(Type.TypeCode.INT)), new Comparisons.SimpleComparison(Comparisons.Type.EQUALS, value)); } - @Nonnull private static QueryPredicate covsEqualsConstraints(int leftTokenIndex, int rightTokenIndex) { final var leftCov = ConstantObjectValue.of(Quantifier.constant(), constantId(leftTokenIndex), Type.primitiveType(Type.TypeCode.INT)); final var rightCov = ConstantObjectValue.of(Quantifier.constant(), constantId(rightTokenIndex), Type.primitiveType(Type.TypeCode.INT)); @@ -221,23 +204,20 @@ private static QueryPredicate covsEqualsConstraints(int leftTokenIndex, int righ return OrPredicate.or(notNullComparison, bothAreNullComparison); } - @Nonnull - private static QueryPlanConstraint cons(@Nonnull final QueryPlanConstraint... constraints) { + private static QueryPlanConstraint cons(final QueryPlanConstraint... constraints) { return QueryPlanConstraint.composeConstraints(Arrays.asList(constraints)); } - @Nonnull - private static QueryPlanConstraint cons(@Nonnull final QueryPredicate... predicates) { + private static QueryPlanConstraint cons(final QueryPredicate... predicates) { return QueryPlanConstraint.ofPredicates(Arrays.asList(predicates)); } - @Nonnull - private PhysicalPlanEquivalence ppe(@Nonnull final QueryPlanConstraint... constraints) { + private PhysicalPlanEquivalence ppe(final QueryPlanConstraint... constraints) { return PhysicalPlanEquivalence.of(QueryPlanConstraint.composeConstraints(Arrays.asList(constraints))); } - private static void cacheShouldBe(@Nonnull RelationalPlanCache cache, - @Nonnull Map> expectedLayout) { + private static void cacheShouldBe(RelationalPlanCache cache, + Map> expectedLayout) { Map> result = new HashMap<>(); for (var key : cache.getStats().getAllKeys()) { for (QueryCacheKey secondaryKey : cache.getStats().getAllSecondaryKeys(key)) { diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/MultiStageCacheTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/MultiStageCacheTests.java index 86da49811e5..665f3c05e01 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/MultiStageCacheTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/MultiStageCacheTests.java @@ -28,9 +28,7 @@ import com.google.common.testing.FakeTicker; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.time.Duration; import java.time.temporal.ChronoUnit; import java.util.EnumMap; @@ -93,31 +91,27 @@ public class MultiStageCacheTests { "Capital", Map.of("Beijing", "Beijing", "Anhui", "Hefei", "Fujian", "Fuzhou", "Gansu", "Lanzhou"))); @Nullable - private static V pickFirst(@Nonnull final Stream stream) { + private static V pickFirst(final Stream stream) { return stream.findFirst().orElse(null); } - @Nonnull - private static String fetchFromCache(@Nonnull final String in) { + private static String fetchFromCache(final String in) { return "restored " + in + " from cache"; } - @Nonnull - private static Pair produceAnimal(@Nonnull final String k2, @Nonnull final String k3) { + private static Pair produceAnimal(final String k2, final String k3) { return Pair.of(k2, entries.get("Animal").get(k2).get(k3)); } - @Nonnull - private static Pair produceLandform(@Nonnull final String k2, @Nonnull final String k3) { + private static Pair produceLandform(final String k2, final String k3) { return Pair.of(k2, entries.get("Landform").get(k2).get(k3)); } - @Nonnull - private static Pair produceCapital(@Nonnull final String k2, @Nonnull final String k3) { + private static Pair produceCapital(final String k2, final String k3) { return Pair.of(k2, entries.get("Capital").get(k2).get(k3)); } - private static void shouldBe(@Nonnull final MultiStageCache cache, Map>> expectedLayout) { + private static void shouldBe(final MultiStageCache cache, Map>> expectedLayout) { Map>> result = new HashMap<>(); for (String key : cache.getStats().getAllKeys()) { result.computeIfAbsent(key, k -> new HashMap<>()); @@ -364,15 +358,15 @@ void removeCacheKeyIfTertiaryIsEmptyWorks() { shouldBe(testCache, Map.of()); } - private static String readCache(@Nonnull MultiStageCache cache, @Nonnull String key, - @Nonnull String secondaryKey, @Nonnull String tertiaryKey) { + private static String readCache(MultiStageCache cache, String key, + String secondaryKey, String tertiaryKey) { return readCache(cache, key, secondaryKey, tertiaryKey, NoOpMetricCollector.INSTANCE); } - private static String readCache(@Nonnull MultiStageCache cache, - @Nonnull String key, @Nonnull String secondaryKey, - @Nonnull String tertiaryKey, - @Nonnull MetricCollector metricCollector) { + private static String readCache(MultiStageCache cache, + String key, String secondaryKey, + String tertiaryKey, + MetricCollector metricCollector) { return cache.reduce(key, secondaryKey, tertiaryKey, () -> NonnullPair.of(tertiaryKey, entries.get(key).get(secondaryKey).get(tertiaryKey)), MultiStageCacheTests::fetchFromCache, @@ -521,16 +515,16 @@ private static class CountMetricCollector implements MetricCollector { private final Map counts = new EnumMap<>(RelationalMetric.RelationalCount.class); @Override - public void increment(@Nonnull final RelationalMetric.RelationalCount count, final int val) { + public void increment(final RelationalMetric.RelationalCount count, final int val) { counts.merge(count, val, Integer::sum); } @Override - public T clock(@Nonnull final RelationalMetric.RelationalEvent event, final com.apple.foundationdb.relational.util.Supplier supplier) throws com.apple.foundationdb.relational.api.exceptions.RelationalException { + public T clock(final RelationalMetric.RelationalEvent event, final com.apple.foundationdb.relational.util.Supplier supplier) throws com.apple.foundationdb.relational.api.exceptions.RelationalException { return supplier.get(); } - public int countEvents(@Nonnull final RelationalMetric.RelationalCount count) { + public int countEvents(final RelationalMetric.RelationalCount count) { return counts.getOrDefault(count, 0); } } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/NoOpMetricCollector.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/NoOpMetricCollector.java index e89c446591e..7088718cc45 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/NoOpMetricCollector.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/NoOpMetricCollector.java @@ -24,9 +24,6 @@ import com.apple.foundationdb.relational.api.metrics.MetricCollector; import com.apple.foundationdb.relational.api.metrics.RelationalMetric; import com.apple.foundationdb.relational.util.Supplier; - -import javax.annotation.Nonnull; - /** * A no-op {@link MetricCollector} for use in tests that do not need to track metrics. */ @@ -38,11 +35,11 @@ private NoOpMetricCollector() { } @Override - public void increment(@Nonnull final RelationalMetric.RelationalCount count, final int val) { + public void increment(final RelationalMetric.RelationalCount count, final int val) { } @Override - public T clock(@Nonnull final RelationalMetric.RelationalEvent event, final Supplier supplier) throws RelationalException { + public T clock(final RelationalMetric.RelationalEvent event, final Supplier supplier) throws RelationalException { return supplier.get(); } } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/PhysicalPlanEquivalenceTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/PhysicalPlanEquivalenceTests.java index ae8a649bee5..34d2067f651 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/PhysicalPlanEquivalenceTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/PhysicalPlanEquivalenceTests.java @@ -32,8 +32,6 @@ import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; - -import javax.annotation.Nonnull; import java.util.Map; import java.util.Set; @@ -45,53 +43,40 @@ */ public class PhysicalPlanEquivalenceTests { - @Nonnull private static final TypeRepository EMPTY_TYPE_REPO = TypeRepository.empty(); - @Nonnull private static final QueryPredicate lt00 = new ValuePredicate(ConstantObjectValue.of(Quantifier.constant(), constantId(0), Type.primitiveType(Type.TypeCode.INT)), new Comparisons.SimpleComparison(Comparisons.Type.LESS_THAN, 100)); - @Nonnull private static final QueryPredicate gt400 = new ValuePredicate(ConstantObjectValue.of(Quantifier.constant(), constantId(0), Type.primitiveType(Type.TypeCode.INT)), new Comparisons.SimpleComparison(Comparisons.Type.GREATER_THAN, 400)); - @Nonnull private static final QueryPredicate lt100Dup = new ValuePredicate(ConstantObjectValue.of(Quantifier.constant(), constantId(0), Type.primitiveType(Type.TypeCode.INT)), new Comparisons.SimpleComparison(Comparisons.Type.LESS_THAN, 100)); - @Nonnull private static final QueryPredicate lt400 = new ValuePredicate(ConstantObjectValue.of(Quantifier.constant(), constantId(0), Type.primitiveType(Type.TypeCode.INT)), new Comparisons.SimpleComparison(Comparisons.Type.LESS_THAN, 400)); - @Nonnull private static final QueryPlanConstraint trueConstraint = QueryPlanConstraint.noConstraint(); - @Nonnull private static final QueryPlanConstraint lt100Constraint = QueryPlanConstraint.ofPredicate(lt00); - @Nonnull private static final QueryPlanConstraint lt100ConstraintDup = QueryPlanConstraint.ofPredicate(lt100Dup); - @Nonnull private static final QueryPlanConstraint gt400Constraint = QueryPlanConstraint.ofPredicate(gt400); - @Nonnull private static final QueryPlanConstraint lt400Constraint = QueryPlanConstraint.ofPredicate(lt400); - @Nonnull private static final EvaluationContext ec80 = EvaluationContext.newBuilder() .setConstant(Quantifier.constant(), Map.of(constantId(0), 80)).build(EMPTY_TYPE_REPO); - @Nonnull private static final EvaluationContext ec120 = EvaluationContext.newBuilder() .setConstant(Quantifier.constant(), Map.of(constantId(0), 120)).build(EMPTY_TYPE_REPO); - @Nonnull private static final EvaluationContext ec120Dup = EvaluationContext.newBuilder() .setConstant(Quantifier.constant(), Map.of(constantId(0), 120)).build(EMPTY_TYPE_REPO); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/RelationalPlanCacheTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/RelationalPlanCacheTests.java index 579b303e599..f8552dd8688 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/RelationalPlanCacheTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/RelationalPlanCacheTests.java @@ -62,9 +62,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.params.ParameterizedTest; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.time.Duration; import java.time.temporal.ChronoUnit; import java.util.Arrays; @@ -101,7 +99,6 @@ public class RelationalPlanCacheTests { public final RelationalConnectionRule connection = new RelationalConnectionRule(database::getConnectionUri) .withSchema("TEST_SCHEMA"); - @Nonnull private static QueryPredicate gte1970p0(final int tokenIndex) { final var builder = RangeConstraints.newBuilder(); builder.addComparisonMaybe(new Comparisons.SimpleComparison(Comparisons.Type.GREATER_THAN_OR_EQUALS, 1970)); @@ -110,7 +107,6 @@ private static QueryPredicate gte1970p0(final int tokenIndex) { constantId(tokenIndex), Type.primitiveType(Type.TypeCode.INT, false)), Type.primitiveType(Type.TypeCode.INT), null), Set.of(builder.build().get())); } - @Nonnull private static QueryPredicate gte1970p1(final int tokenIndex) { final var builder = RangeConstraints.newBuilder(); builder.addComparisonMaybe(new Comparisons.SimpleComparison(Comparisons.Type.GREATER_THAN_OR_EQUALS, 1970)); @@ -119,8 +115,7 @@ private static QueryPredicate gte1970p1(final int tokenIndex) { constantId(tokenIndex), Type.primitiveType(Type.TypeCode.INT, false)), Type.primitiveType(Type.TypeCode.INT), null), Set.of(builder.build().get())); } - @Nonnull - private static QueryPredicate gte1980p0(final int tokenIndex, @Nonnull Optional scope) { + private static QueryPredicate gte1980p0(final int tokenIndex, Optional scope) { final var builder = RangeConstraints.newBuilder(); builder.addComparisonMaybe(new Comparisons.SimpleComparison(Comparisons.Type.GREATER_THAN_OR_EQUALS, 1980)); builder.addComparisonMaybe(new Comparisons.SimpleComparison(Comparisons.Type.LESS_THAN_OR_EQUALS, 1989)); @@ -128,7 +123,6 @@ private static QueryPredicate gte1980p0(final int tokenIndex, @Nonnull Optional< constantId(tokenIndex, scope), Type.primitiveType(Type.TypeCode.INT, false)), Type.primitiveType(Type.TypeCode.INT), null), Set.of(builder.build().get())); } - @Nonnull private static QueryPredicate gte1980p1(final int tokenIndex) { final var builder = RangeConstraints.newBuilder(); builder.addComparisonMaybe(new Comparisons.SimpleComparison(Comparisons.Type.GREATER_THAN_OR_EQUALS, 1980)); @@ -137,7 +131,6 @@ private static QueryPredicate gte1980p1(final int tokenIndex) { constantId(tokenIndex), Type.primitiveType(Type.TypeCode.INT, false)), Type.primitiveType(Type.TypeCode.INT), null), Set.of(builder.build().get())); } - @Nonnull private static QueryPredicate gte1990p0(final int tokenIndex) { final var builder = RangeConstraints.newBuilder(); builder.addComparisonMaybe(new Comparisons.SimpleComparison(Comparisons.Type.GREATER_THAN_OR_EQUALS, 1990)); @@ -146,7 +139,6 @@ private static QueryPredicate gte1990p0(final int tokenIndex) { constantId(tokenIndex), Type.primitiveType(Type.TypeCode.INT, false)), Type.primitiveType(Type.TypeCode.INT), null), Set.of(builder.build().get())); } - @Nonnull private static QueryPredicate gte1990p1(final int tokenIndex) { final var builder = RangeConstraints.newBuilder(); builder.addComparisonMaybe(new Comparisons.SimpleComparison(Comparisons.Type.GREATER_THAN_OR_EQUALS, 1990)); @@ -156,30 +148,25 @@ private static QueryPredicate gte1990p1(final int tokenIndex) { } // todo (yhatem) clean this up. - @Nonnull private static QueryPredicate ofTypeIntp0(final int tokenIndex) { return new ValuePredicate(OfTypeValue.of(ConstantObjectValue.of(Quantifier.constant(), constantId(tokenIndex), Type.primitiveType(Type.TypeCode.INT)), Type.primitiveType(Type.TypeCode.INT, false)), new Comparisons.SimpleComparison(Comparisons.Type.EQUALS, true)); } - @Nonnull private static QueryPredicate ofTypeIntp1(final int tokenIndex) { return ofTypeInt(tokenIndex, Optional.empty()); } - @Nonnull private static QueryPredicate strEq(final int tokenIndex1, final String scope1, final int tokenIndex2, final String scope2) { return strEq(tokenIndex1, Optional.of(scope1), tokenIndex2, Optional.of(scope2)); } - @Nonnull private static QueryPredicate strEq(final int tokenIndex1, final int tokenIndex2) { return strEq(tokenIndex1, Optional.empty(), tokenIndex2, Optional.empty()); } @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - @Nonnull private static QueryPredicate strEq(final int tokenIndex1, final Optional scope1, final int tokenIndex2, final Optional scope2) { final var leftCov = ConstantObjectValue.of(Quantifier.constant(), constantId(tokenIndex1, scope1), Type.primitiveType(Type.TypeCode.STRING)); final var rightCov = ConstantObjectValue.of(Quantifier.constant(), constantId(tokenIndex2, scope2), Type.primitiveType(Type.TypeCode.STRING)); @@ -196,45 +183,37 @@ private static QueryPredicate strEq(final int tokenIndex1, final Optional scope1, final int tokenIndex2, final Optional scope2) { return QueryPlanConstraint.ofPredicate(strEq(tokenIndex1, scope1, tokenIndex2, scope2)); } - @Nonnull private static QueryPlanConstraint isNotNullInt(final int tokenIndex) { return QueryPlanConstraint.ofPredicate(isNotNull(tokenIndex, Optional.empty(), Type.primitiveType(Type.TypeCode.INT))); } - @Nonnull private static QueryPlanConstraint isNotNullInt(final int tokenIndex, final String scope) { return QueryPlanConstraint.ofPredicate(isNotNull(tokenIndex, Optional.of(scope), Type.primitiveType(Type.TypeCode.INT))); } - @Nonnull private static QueryPlanConstraint isNotNullStr(final int tokenIndex) { return QueryPlanConstraint.ofPredicate(isNotNull(tokenIndex, Optional.empty(), Type.primitiveType(Type.TypeCode.STRING))); } - @Nonnull private static QueryPlanConstraint isNotNullStr(final int tokenIndex, final String scope) { return QueryPlanConstraint.ofPredicate(isNotNull(tokenIndex, Optional.of(scope), Type.primitiveType(Type.TypeCode.STRING))); } @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - @Nonnull private static QueryPredicate isNotNull(final int tokenIndex, final Optional scope, Type type) { return new ValuePredicate(EvaluatesToValue.isNotNull( ConstantObjectValue.of(Quantifier.constant(), constantId(tokenIndex, scope), type)), @@ -242,120 +221,96 @@ private static QueryPredicate isNotNull(final int tokenIndex, final Optional scope) { return new ValuePredicate(OfTypeValue.of(ConstantObjectValue.of(Quantifier.constant(), constantId(tokenIndex, scope), Type.primitiveType(Type.TypeCode.INT)), Type.primitiveType(Type.TypeCode.INT, false)), new Comparisons.SimpleComparison(Comparisons.Type.EQUALS, true)); } - @Nonnull private static QueryPredicate ofTypeString(final int tokenIndex, final String scope) { return ofTypeString(tokenIndex, Optional.of(scope)); } @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - @Nonnull private static QueryPredicate ofTypeString(final int tokenIndex, final Optional scope) { return new ValuePredicate(OfTypeValue.of(ConstantObjectValue.of(Quantifier.constant(), constantId(tokenIndex, scope), Type.primitiveType(Type.TypeCode.STRING)), Type.primitiveType(Type.TypeCode.STRING, false)), new Comparisons.SimpleComparison(Comparisons.Type.EQUALS, true)); } - @Nonnull private static QueryPlanConstraint ofTypeStringCons(final int tokenIndex) { return QueryPlanConstraint.ofPredicate(ofTypeString(tokenIndex, Optional.empty())); } - @Nonnull private static QueryPlanConstraint ofTypeStringCons(final int tokenIndex, final String scope) { return QueryPlanConstraint.ofPredicate(ofTypeString(tokenIndex, scope)); } - @Nonnull private static QueryPlanConstraint c1970Cp0(final int tokenIndex) { return QueryPlanConstraint.ofPredicate(gte1970p0(tokenIndex)); } - @Nonnull private static QueryPlanConstraint c1970Cp1(final int tokenIndex) { return QueryPlanConstraint.ofPredicate(gte1970p1(tokenIndex)); } - @Nonnull private static QueryPlanConstraint c1980Cp0(final int tokenIndex) { return c1980Cp0(tokenIndex, null); } - @Nonnull private static QueryPlanConstraint c1980Cp0(final int tokenIndex, @Nullable String scope) { return QueryPlanConstraint.ofPredicate(gte1980p0(tokenIndex, Optional.ofNullable(scope))); } - @Nonnull private static QueryPlanConstraint c1980Cp1(final int tokenIndex) { return QueryPlanConstraint.ofPredicate(gte1980p1(tokenIndex)); } - @Nonnull private static QueryPlanConstraint c1990Cp0(final int tokenIndex) { return QueryPlanConstraint.ofPredicate(gte1990p0(tokenIndex)); } - @Nonnull private static QueryPlanConstraint c1990Cp1(final int tokenIndex) { return QueryPlanConstraint.ofPredicate(gte1990p1(tokenIndex)); } - @Nonnull private static QueryPlanConstraint ofTypeIntCp0(final int tokenIndex) { return QueryPlanConstraint.ofPredicate(ofTypeIntp0(tokenIndex)); } - @Nonnull private static QueryPlanConstraint ofTypeIntCp1(final int tokenIndex) { return QueryPlanConstraint.ofPredicate(ofTypeIntp1(tokenIndex)); } - @Nonnull private static QueryPlanConstraint ofTypeIntCons(final int tokenIndex, @Nullable String scope) { return QueryPlanConstraint.ofPredicate(ofTypeInt(tokenIndex, Optional.ofNullable(scope))); } - @Nonnull private static final QueryPlanConstraint tautology = QueryPlanConstraint.noConstraint(); - @Nonnull private static final String i1970 = "IDX_1970"; - @Nonnull private static final String i1980 = "IDX_1980"; - @Nonnull private static final String i1990 = "IDX_1990"; - @Nonnull private static final String i2000 = "IDX_2000"; - @Nonnull private static final String Scan = "SCAN"; - @Nonnull - private PlannerConfiguration configOf(@Nonnull final Set readableIndexes) { + private PlannerConfiguration configOf(final Set readableIndexes) { return configOf(readableIndexes, Options.none()); } - @Nonnull - private PlannerConfiguration configOf(@Nonnull final Set readableIndexes, @Nonnull final Options options) { + private PlannerConfiguration configOf(final Set readableIndexes, final Options options) { return PlannerConfiguration.of(Optional.of(readableIndexes), options); } - @Nonnull - private PlanGenerator getPlanGenerator(@Nonnull final RelationalPlanCache cache, - @Nonnull final String schemaTemplateName, + private PlanGenerator getPlanGenerator(final RelationalPlanCache cache, + final String schemaTemplateName, int schemaTemplateVersion, - @Nonnull final Set readableIndexes, - @Nonnull final Options options) throws Exception { + final Set readableIndexes, + final Options options) throws Exception { final var schemaName = connection.getSchema(); final var embeddedConnection = Assert.castUnchecked(connection.getUnderlyingEmbeddedConnection(), EmbeddedRelationalConnection.class); final var schemaTemplate = embeddedConnection.getSchemaTemplate().unwrap(RecordLayerSchemaTemplate.class).toBuilder().setVersion(schemaTemplateVersion).setName(schemaTemplateName).build(); @@ -373,15 +328,13 @@ private PlanGenerator getPlanGenerator(@Nonnull final RelationalPlanCache cache, return PlanGenerator.create(Optional.of(cache), planContext, store.getRecordMetaData(), storeState, store.getIndexMaintainerRegistry(), options); } - @Nonnull private Plan.ExecutionContext getExecutionContext() throws RelationalException { final var embeddedConnection = Assert.castUnchecked(connection.getUnderlyingEmbeddedConnection(), EmbeddedRelationalConnection.class); return Plan.ExecutionContext.of(embeddedConnection.getTransaction(), Options.builder().build(), embeddedConnection, Assert.notNullUnchecked(embeddedConnection.getMetricCollector())); } - @Nonnull - private static String inferScanType(@Nonnull final Plan plan) { + private static String inferScanType(final Plan plan) { Assertions.assertTrue(plan instanceof QueryPlan.PhysicalQueryPlan); final var physicalPlan = (QueryPlan.PhysicalQueryPlan) plan; final var desc = physicalPlan.getRecordQueryPlan().toString(); // very ad-hoc :/ @@ -398,12 +351,11 @@ private static String inferScanType(@Nonnull final Plan plan) { } } - @Nonnull - private static QueryPlanConstraint cons(@Nonnull final QueryPlanConstraint... constraints) { + private static QueryPlanConstraint cons(final QueryPlanConstraint... constraints) { return QueryPlanConstraint.composeConstraints(Arrays.asList(constraints)); } - private static void shouldBe(@Nonnull final RelationalPlanCache cache, @Nonnull final Map> expectedLayout) { + private static void shouldBe(final RelationalPlanCache cache, final Map> expectedLayout) { Map> result = new HashMap<>(); for (String key : cache.getStats().getAllKeys()) { for (QueryCacheKey secondaryKey : cache.getStats().getAllSecondaryKeys(key)) { @@ -425,8 +377,7 @@ private static void shouldBe(@Nonnull final RelationalPlanCache cache, @Nonnull .hasSameSizeAs(expectedLayout); } - @Nonnull - private RelationalPlanCache getCache(@Nonnull final FakeTicker ticker) { + private RelationalPlanCache getCache(final FakeTicker ticker) { final var relationalCache = RelationalPlanCache.newRelationalCacheBuilder() .setExecutor(Runnable::run) .setSize(2) @@ -443,50 +394,49 @@ private RelationalPlanCache getCache(@Nonnull final FakeTicker ticker) { return relationalCache; } - @Nonnull - private PhysicalPlanEquivalence ppe(@Nonnull final QueryPlanConstraint... constraints) { + private PhysicalPlanEquivalence ppe(final QueryPlanConstraint... constraints) { return PhysicalPlanEquivalence.of(QueryPlanConstraint.composeConstraints(Arrays.asList(constraints))); } - private void planQuery(@Nonnull final RelationalPlanCache cache, - @Nonnull final String query, - @Nonnull final String schemaTemplateName, + private void planQuery(final RelationalPlanCache cache, + final String query, + final String schemaTemplateName, int schemaTemplateVersion, - @Nonnull final Set readableIndexes, - @Nonnull final String expectedPhysicalPlan) throws Exception { + final Set readableIndexes, + final String expectedPhysicalPlan) throws Exception { planQuery(cache, query, schemaTemplateName, schemaTemplateVersion, readableIndexes, Options.none(), expectedPhysicalPlan); } - private void planQuery(@Nonnull final RelationalPlanCache cache, - @Nonnull final String query, - @Nonnull final String schemaTemplateName, + private void planQuery(final RelationalPlanCache cache, + final String query, + final String schemaTemplateName, int schemaTemplateVersion, - @Nonnull final Set readableIndexes, - @Nonnull final Options options, @Nonnull final String expectedPhysicalPlan) throws Exception { + final Set readableIndexes, + final Options options, final String expectedPhysicalPlan) throws Exception { planQueryWithTemporaryFunctionsPreamble(cache, ImmutableList.of(), query, schemaTemplateName, schemaTemplateVersion, readableIndexes, options, expectedPhysicalPlan); } - private void planQueryWithTemporaryFunctionsPreamble(@Nonnull final RelationalPlanCache cache, - @Nonnull final List temporaryFunctionsDefinitions, - @Nonnull final String query, - @Nonnull final String schemaTemplateName, + private void planQueryWithTemporaryFunctionsPreamble(final RelationalPlanCache cache, + final List temporaryFunctionsDefinitions, + final String query, + final String schemaTemplateName, int schemaTemplateVersion, - @Nonnull final Set readableIndexes, - @Nonnull final String expectedPhysicalPlan) throws Exception { + final Set readableIndexes, + final String expectedPhysicalPlan) throws Exception { planQueryWithTemporaryFunctionsPreamble(cache, temporaryFunctionsDefinitions, query, schemaTemplateName, schemaTemplateVersion, readableIndexes, Options.none(), expectedPhysicalPlan); } - private void planQueryWithTemporaryFunctionsPreamble(@Nonnull final RelationalPlanCache cache, - @Nonnull final List temporaryFunctionsDefinitions, - @Nonnull final String query, - @Nonnull final String schemaTemplateName, + private void planQueryWithTemporaryFunctionsPreamble(final RelationalPlanCache cache, + final List temporaryFunctionsDefinitions, + final String query, + final String schemaTemplateName, int schemaTemplateVersion, - @Nonnull final Set readableIndexes, - @Nonnull final Options options, - @Nonnull final String expectedPhysicalPlan) throws Exception { + final Set readableIndexes, + final Options options, + final String expectedPhysicalPlan) throws Exception { connection.setAutoCommit(false); connection.getUnderlyingEmbeddedConnection().createNewTransaction(); var planGenerator = getPlanGenerator(cache, schemaTemplateName, schemaTemplateVersion, readableIndexes, options); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/ValueSpecificConstraintTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/ValueSpecificConstraintTests.java index d4d14955245..7d73ad84c07 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/ValueSpecificConstraintTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/ValueSpecificConstraintTests.java @@ -37,8 +37,6 @@ import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; - -import javax.annotation.Nonnull; import java.net.URI; import java.util.Map; import java.util.TreeMap; @@ -57,20 +55,20 @@ public ValueSpecificConstraintTests() { Utils.enableCascadesDebugger(); } - private void queryShouldMissCache(@Nonnull final RelationalConnection connection, @Nonnull final String query) throws Exception { + private void queryShouldMissCache(final RelationalConnection connection, final String query) throws Exception { final var queryWithCacheLoggingOption = query + " options (log query)"; connection.createStatement().executeQuery(queryWithCacheLoggingOption); Assertions.assertTrue(logAppender.lastMessageIsCacheMiss()); } - private void queryShouldHitCache(@Nonnull final RelationalConnection connection, @Nonnull final String query) throws Exception { + private void queryShouldHitCache(final RelationalConnection connection, final String query) throws Exception { final var queryWithCacheLoggingOption = query + " options (log query)"; connection.createStatement().executeQuery(queryWithCacheLoggingOption); Assertions.assertTrue(logAppender.lastMessageIsCacheHit()); } - private void preparedQueryShouldMissCache(@Nonnull final RelationalConnection connection, @Nonnull final String query, - @Nonnull final Map preparedParams) throws Exception { + private void preparedQueryShouldMissCache(final RelationalConnection connection, final String query, + final Map preparedParams) throws Exception { final var queryWithCacheLoggingOption = query + " options (log query)"; final var statement = connection.prepareStatement(queryWithCacheLoggingOption); for (final var entry : preparedParams.entrySet()) { @@ -80,8 +78,8 @@ private void preparedQueryShouldMissCache(@Nonnull final RelationalConnection co Assertions.assertTrue(logAppender.lastMessageIsCacheMiss()); } - private void preparedQueryShouldHitCache(@Nonnull final RelationalConnection connection, @Nonnull final String query, - @Nonnull final Map preparedParams) throws Exception { + private void preparedQueryShouldHitCache(final RelationalConnection connection, final String query, + final Map preparedParams) throws Exception { final var queryWithCacheLoggingOption = query + " options (log query)"; final var statement = connection.prepareStatement(queryWithCacheLoggingOption); for (final var entry : preparedParams.entrySet()) { diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/package-info.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/package-info.java new file mode 100644 index 00000000000..95e8f0d7b5a --- /dev/null +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/package-info.java @@ -0,0 +1,24 @@ +/* + * package-info.java + * + * This source file is part of the FoundationDB open source project + * + * Copyright 2021-2025 Apple Inc. and the FoundationDB project authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@NullMarked +package com.apple.foundationdb.relational.recordlayer.query.cache; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/functions/CompilableSqlFunctionTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/functions/CompilableSqlFunctionTest.java index 3b80d5a6814..ff0f2c4613a 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/functions/CompilableSqlFunctionTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/functions/CompilableSqlFunctionTest.java @@ -27,8 +27,6 @@ import com.google.common.collect.ImmutableList; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; - -import javax.annotation.Nonnull; import java.util.Optional; /** @@ -49,7 +47,6 @@ void toProtoThrowsRecordCoreException() { /** * Creates a simple test function with basic parameters. */ - @Nonnull private CompiledSqlFunction createTestFunction() { return new CompiledSqlFunction( "testFunction", @@ -70,7 +67,6 @@ private CompiledSqlFunction createTestFunction() { /** * Creates a dummy relational expression to use as function body. */ - @Nonnull private RelationalExpression createDummyBody() { // Create a minimal SelectExpression as the function body return new SelectExpression( diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/functions/IncarnationTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/functions/IncarnationTest.java index 1ecf6434051..de8b6d2359a 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/functions/IncarnationTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/functions/IncarnationTest.java @@ -38,8 +38,6 @@ import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; - -import javax.annotation.Nonnull; import java.sql.SQLException; import java.util.List; import java.util.function.IntFunction; @@ -125,7 +123,7 @@ void incarnationWithContinuations() throws SQLException, RelationalException { } } - private void updateIncarnation(@Nonnull final IntFunction updater) throws SQLException, RelationalException { + private void updateIncarnation(final IntFunction updater) throws SQLException, RelationalException { connection.setAutoCommit(false); // force transaction to start, because at the time of writing, we don't support BEGIN TRANSACTION statement.executeQuery("SELECT key FROM my_record"); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedMacroFunctionBuilderTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedMacroFunctionBuilderTest.java index d41c20089b3..b4709510d36 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedMacroFunctionBuilderTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedMacroFunctionBuilderTest.java @@ -35,9 +35,6 @@ import com.apple.foundationdb.relational.recordlayer.query.Literals; import com.google.common.collect.ImmutableList; import org.junit.jupiter.api.Test; - -import javax.annotation.Nonnull; - import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -46,7 +43,6 @@ */ final class UserDefinedMacroFunctionBuilderTest { - @Nonnull private static final Type STRING_TYPE = Type.primitiveType(Type.TypeCode.STRING); @Test @@ -158,8 +154,7 @@ void setLiteralsThrowsUnsupportedOperationException() { * Creates a named string parameter with no default value, mirroring how the DDL visitor models a parameter * declaration without a {@code DEFAULT} clause. */ - @Nonnull - private static Expression stringParameter(@Nonnull final String name) { + private static Expression stringParameter(final String name) { return Expression.of(new ThrowsValue(STRING_TYPE), Identifier.of(name)); } } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/functions/package-info.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/functions/package-info.java new file mode 100644 index 00000000000..0709a5dc871 --- /dev/null +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/functions/package-info.java @@ -0,0 +1,24 @@ +/* + * package-info.java + * + * This source file is part of the FoundationDB open source project + * + * Copyright 2021-2025 Apple Inc. and the FoundationDB project authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@NullMarked +package com.apple.foundationdb.relational.recordlayer.query.functions; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/package-info.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/package-info.java new file mode 100644 index 00000000000..034903ec2e9 --- /dev/null +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/package-info.java @@ -0,0 +1,24 @@ +/* + * package-info.java + * + * This source file is part of the FoundationDB open source project + * + * Copyright 2021-2025 Apple Inc. and the FoundationDB project authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@NullMarked +package com.apple.foundationdb.relational.recordlayer.query; + +import org.jspecify.annotations.NullMarked; From caea81fc81d6888c1f30bc8d205aa320c9b62bb2 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Fri, 28 Aug 2026 18:41:15 +0200 Subject: [PATCH 03/42] Mechanical jspecify swap: fdb-relational-core recordlayer infrastructure packages --- .../recordlayer/AbstractDatabase.java | 24 +-- .../AbstractEmbeddedStatement.java | 17 +- .../relational/recordlayer/AbstractRow.java | 2 +- .../recordlayer/CatalogMetaData.java | 7 +- .../recordlayer/ContinuationBuilder.java | 16 +- .../recordlayer/ContinuationImpl.java | 9 +- .../recordlayer/DirectScannable.java | 8 +- .../EmbeddedRelationalConnection.java | 26 +-- .../EmbeddedRelationalPreparedStatement.java | 9 +- .../EmbeddedRelationalStatement.java | 24 ++- .../recordlayer/ErrorCapturingResultSet.java | 2 - .../relational/recordlayer/FDBTuple.java | 4 +- .../recordlayer/HollowTransactionManager.java | 3 +- .../recordlayer/ImmutableKeyValue.java | 3 +- .../recordlayer/IteratorResultSet.java | 2 - .../relational/recordlayer/KeyBuilder.java | 3 - .../relational/recordlayer/KeySpaceUtils.java | 38 ++--- .../relational/recordlayer/MessageTuple.java | 3 +- .../relational/recordlayer/QueryExecutor.java | 12 +- .../recordlayer/QueryPropertiesUtils.java | 5 +- .../recordlayer/RecordContextTransaction.java | 9 +- .../recordlayer/RecordLayerDatabase.java | 13 +- .../recordlayer/RecordLayerEngine.java | 13 +- .../recordlayer/RecordLayerIterator.java | 5 +- .../recordlayer/RecordLayerResultSet.java | 19 +-- .../recordlayer/RecordLayerSchema.java | 9 +- .../RecordLayerStorageCluster.java | 7 +- .../RecordLayerTransactionManager.java | 5 +- ...ecordStoreAndRecordContextTransaction.java | 5 +- .../recordlayer/RecordStoreIndex.java | 6 +- .../recordlayer/RecordTypeScannable.java | 5 +- .../recordlayer/RecordTypeTable.java | 23 ++- .../RelationalKeyspaceProvider.java | 27 +--- .../relational/recordlayer/Table.java | 11 +- .../catalog/CachedMetaDataStore.java | 3 +- .../catalog/CatalogMetaDataProvider.java | 10 +- .../catalog/CatalogMetaDataStore.java | 3 +- .../catalog/RecordLayerStoreCatalog.java | 56 +++---- ...RecordLayerStoreSchemaTemplateCatalog.java | 32 ++-- .../catalog/RecordLayerStoreUtils.java | 3 +- .../catalog/RecordMetaDataStore.java | 3 +- .../catalog/StoreCatalogProvider.java | 5 +- .../catalog/TransactionBoundDatabase.java | 15 +- .../recordlayer/catalog/package-info.java | 3 + .../systables/DatabaseInfoSystemTable.java | 5 +- .../catalog/systables/SchemaSystemTable.java | 5 +- .../systables/SchemaTemplateSystemTable.java | 5 +- .../catalog/systables/SystemTable.java | 5 +- .../systables/SystemTableRegistry.java | 3 - .../catalog/systables/package-info.java | 3 + .../AbstractMetadataOperationsFactory.java | 27 ++-- .../ddl/CreateDatabaseConstantAction.java | 7 +- ...CreateTemporaryFunctionConstantAction.java | 9 +- .../DropTemporaryFunctionConstantAction.java | 4 +- .../ddl/NoOpMetadataOperationsFactory.java | 27 ++-- .../ddl/RecordLayerCatalogQueryFactory.java | 7 +- .../RecordLayerMetadataOperationsFactory.java | 30 ++-- .../ThrowingMetadataOperationsFactory.java | 27 ++-- .../recordlayer/ddl/package-info.java | 3 + .../recordlayer/metadata/DataTypeUtils.java | 8 +- .../metadata/NoOpSchemaTemplate.java | 31 +--- .../metadata/RecordLayerColumn.java | 16 +- .../metadata/RecordLayerIndex.java | 74 +++------ .../metadata/RecordLayerInvokedRoutine.java | 47 ++---- .../metadata/RecordLayerSchema.java | 13 +- .../metadata/RecordLayerSchemaTemplate.java | 149 +++++------------- .../metadata/RecordLayerTable.java | 117 +++++--------- .../recordlayer/metadata/RecordLayerView.java | 27 +--- .../recordlayer/metadata/SkeletonVisitor.java | 19 ++- .../recordlayer/metadata/package-info.java | 3 + .../serde/FileDescriptorSerializer.java | 21 +-- .../serde/RecordMetadataDeserializer.java | 50 +++--- .../serde/RecordMetadataSerializer.java | 17 +- .../metadata/serde/RoutineParser.java | 32 ++-- .../metadata/serde/package-info.java | 3 + .../metric/StoreTimerMetricCollector.java | 22 ++- .../recordlayer/metric/package-info.java | 3 + .../relational/recordlayer/package-info.java | 3 + .../BackingLocatableResolverStore.java | 4 +- .../storage/BackingRecordStore.java | 8 +- .../recordlayer/storage/BackingStore.java | 2 +- .../LocatableResolverMetaDataProvider.java | 16 +- .../recordlayer/storage/StoreConfig.java | 8 +- .../recordlayer/storage/package-info.java | 3 + .../expression/ExpressionFactoryImpl.java | 13 +- .../structuredsql/expression/FieldImpl.java | 24 +-- .../expression/package-info.java | 3 + .../StatementBuilderFactoryImpl.java | 20 +-- .../statement/UpdateStatementImpl.java | 117 ++++---------- .../structuredsql/statement/package-info.java | 3 + .../recordlayer/util/ExceptionUtil.java | 4 +- .../relational/recordlayer/util/Hex.java | 2 +- .../recordlayer/util/MemoizedFunction.java | 6 +- .../util/MetricRegistryStoreTimer.java | 11 +- .../recordlayer/util/TypeUtils.java | 11 +- .../recordlayer/util/package-info.java | 3 + ...nsactionBoundEmbeddedRelationalEngine.java | 7 +- .../TransactionBoundStorageCluster.java | 5 +- .../catalog/HollowSchemaTemplateCatalog.java | 19 +-- .../catalog/HollowStoreCatalog.java | 31 ++-- .../catalog/package-info.java | 5 +- .../transactionbound/package-info.java | 3 + .../AbstractRecordLayerResultSetTest.java | 2 - .../recordlayer/AutoCommitTests.java | 9 +- .../CaseSensitiveDbObjectsTest.java | 2 - .../recordlayer/CopyCommandTest.java | 33 ++-- .../EmbeddedRelationalExtension.java | 21 +-- .../relational/recordlayer/FDBTupleTest.java | 3 - .../recordlayer/KeySpacePathParsingTest.java | 14 +- .../recordlayer/LogAppenderRule.java | 8 +- .../recordlayer/MessageTupleTest.java | 2 - .../OfflinePlanGenerationTest.java | 2 - .../recordlayer/PlaceholderCatalog.java | 2 +- .../recordlayer/PlanGenerationStackTest.java | 5 +- .../recordlayer/QueryPropertiesTest.java | 3 +- .../recordlayer/RelationalArrayTest.java | 7 +- .../recordlayer/RelationalConnectionRule.java | 4 - .../recordlayer/RelationalExtension.java | 2 +- .../RelationalKeyspaceProviderTest.java | 3 - .../recordlayer/RelationalStatementRule.java | 13 +- .../recordlayer/SqlFunctionsTest.java | 2 - .../recordlayer/SystemCatalogQueryTest.java | 11 +- .../TransactionBoundDatabaseTest.java | 32 ++-- .../TransactionBoundDatabaseWithEnumTest.java | 3 +- .../recordlayer/UniqueIndexTests.java | 5 +- .../relational/recordlayer/Utils.java | 5 +- .../RecordLayerStoreCatalogImplTest.java | 21 ++- .../RecordLayerStoreCatalogTestBase.java | 19 +-- .../metadata/RecordLayerColumnTests.java | 4 +- .../metadata/RecordLayerViewTests.java | 2 - .../metadata/SchemaTemplateSerDeTests.java | 22 +-- ...tricCollectorFromFDBRecordContextTest.java | 9 +- .../BackingLocatableResolverStoreTest.java | 15 +- .../util/MemoizedFunctionTest.java | 2 - 134 files changed, 678 insertions(+), 1266 deletions(-) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/AbstractDatabase.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/AbstractDatabase.java index 2a49364c9e9..1b4d1933cb5 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/AbstractDatabase.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/AbstractDatabase.java @@ -32,8 +32,7 @@ import com.apple.foundationdb.relational.recordlayer.query.cache.RelationalPlanCache; import com.apple.foundationdb.relational.recordlayer.storage.BackingStore; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.net.URI; import java.sql.SQLException; import java.util.HashMap; @@ -41,34 +40,30 @@ public abstract class AbstractDatabase implements RelationalDatabase { - @Nonnull private final MetadataOperationsFactory metadataOperationsFactory; - @Nonnull private final DdlQueryFactory ddlQueryFactory; @Nullable protected EmbeddedRelationalConnection connection; final Map schemas = new HashMap<>(); @Nullable private final RelationalPlanCache planCache; - @Nonnull protected Options options; - public AbstractDatabase(@Nonnull final MetadataOperationsFactory metadataOperationsFactory, - @Nonnull DdlQueryFactory ddlQueryFactory, + public AbstractDatabase(final MetadataOperationsFactory metadataOperationsFactory, + DdlQueryFactory ddlQueryFactory, @Nullable RelationalPlanCache planCache, - @Nonnull Options options) { + Options options) { this.metadataOperationsFactory = metadataOperationsFactory; this.ddlQueryFactory = ddlQueryFactory; this.planCache = planCache; this.options = options; } - protected void setConnection(@Nonnull EmbeddedRelationalConnection conn) { + protected void setConnection(EmbeddedRelationalConnection conn) { this.connection = conn; } - @Nonnull protected Transaction getCurrentTransaction() throws RelationalException { if (connection == null) { throw new RelationalException("Connection not set!", ErrorCode.INTERNAL_ERROR); @@ -78,7 +73,7 @@ protected Transaction getCurrentTransaction() throws RelationalException { @Override @SuppressWarnings("PMD.CloseResource") - public @Nonnull RecordLayerSchema loadSchema(@Nonnull String schemaId) throws RelationalException { + public RecordLayerSchema loadSchema(String schemaId) throws RelationalException { RecordLayerSchema schema = schemas.get(schemaId); boolean putBack = false; if (schema == null) { @@ -104,18 +99,16 @@ protected Transaction getCurrentTransaction() throws RelationalException { return schema; } - @Nonnull @Override public MetadataOperationsFactory getDdlFactory() { return metadataOperationsFactory; } - @Nonnull public DdlQueryFactory getDdlQueryFactory() { return ddlQueryFactory; } - public abstract BackingStore loadRecordStore(@Nonnull String schemaId, @Nonnull FDBRecordStoreBase.StoreExistenceCheck existenceCheck) throws RelationalException; + public abstract BackingStore loadRecordStore(String schemaId, FDBRecordStoreBase.StoreExistenceCheck existenceCheck) throws RelationalException; public abstract URI getURI(); @@ -126,12 +119,11 @@ public RelationalPlanCache getPlanCache() { return planCache; } - @Nonnull public Options getOptions() { return options; } - public void setOption(@Nonnull Options.Name name, Object value) throws SQLException { + public void setOption(Options.Name name, Object value) throws SQLException { options = options.withOption(name, value); } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/AbstractEmbeddedStatement.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/AbstractEmbeddedStatement.java index 7967b5853cf..03be6817061 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/AbstractEmbeddedStatement.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/AbstractEmbeddedStatement.java @@ -34,8 +34,7 @@ import com.apple.foundationdb.relational.recordlayer.util.ExceptionUtil; import com.apple.foundationdb.relational.util.Assert; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Optional; @@ -45,7 +44,6 @@ * Should be used by classes that derive {@link com.apple.foundationdb.relational.api.RelationalPreparedStatement} and {@link com.apple.foundationdb.relational.api.RelationalStatement} */ public abstract class AbstractEmbeddedStatement implements java.sql.Statement { - @Nonnull final EmbeddedRelationalConnection conn; @Nullable @@ -58,14 +56,13 @@ public abstract class AbstractEmbeddedStatement implements java.sql.Statement { Options options; - public AbstractEmbeddedStatement(@Nonnull final EmbeddedRelationalConnection conn) { + public AbstractEmbeddedStatement(final EmbeddedRelationalConnection conn) { this.conn = conn; this.options = conn.getOptions(); } - @Nonnull - abstract PlanContext createPlanContext(@Nonnull FDBRecordStoreBase store, - @Nonnull Options options) throws RelationalException; + abstract PlanContext createPlanContext(FDBRecordStoreBase store, + Options options) throws RelationalException; @SuppressWarnings("PMD.PreserveStackTrace") public boolean executeInternal(String sql) throws SQLException, RelationalException { @@ -108,7 +105,7 @@ public boolean executeInternal(String sql) throws SQLException, RelationalExcept }); } - private boolean clockAndExecuteQueryPlan(@Nonnull final QueryPlan plan, @Nonnull final Plan.ExecutionContext executionContext) throws RelationalException { + private boolean clockAndExecuteQueryPlan(final QueryPlan plan, final Plan.ExecutionContext executionContext) throws RelationalException { final var metricCollector = Assert.notNullUnchecked(conn.getMetricCollector()); return metricCollector.clock(RelationalMetric.RelationalEvent.EXECUTE_QUERY_PLAN, () -> { currentResultSet = new ErrorCapturingResultSet(plan.execute(executionContext)); @@ -131,7 +128,7 @@ private boolean clockAndExecuteQueryPlan(@Nonnull final QueryPlan plan, @Nonnull }); } - private boolean clockAndExecuteNonQueryPlan(@Nonnull final Plan plan, @Nonnull final Plan.ExecutionContext executionContext) throws RelationalException { + private boolean clockAndExecuteNonQueryPlan(final Plan plan, final Plan.ExecutionContext executionContext) throws RelationalException { final var metricCollector = Assert.notNullUnchecked(conn.getMetricCollector()); return metricCollector.clock(RelationalMetric.RelationalEvent.EXECUTE_NON_QUERY_PLAN, () -> { plan.execute(executionContext); @@ -209,7 +206,7 @@ void checkOpen() throws SQLException { } } - private int countUpdates(@Nonnull ResultSet resultSet) throws SQLException { + private int countUpdates(ResultSet resultSet) throws SQLException { /* * This is a bit of a temporary hack both to address a bug(TODO), and also to get around the * way that RecordLayer DML plans are executed. diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/AbstractRow.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/AbstractRow.java index bf0274bb32e..53ee6fa759b 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/AbstractRow.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/AbstractRow.java @@ -32,7 +32,7 @@ import com.google.protobuf.Descriptors; import com.google.protobuf.Message; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.Arrays; import java.util.Collection; import java.util.Objects; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/CatalogMetaData.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/CatalogMetaData.java index 759e071d795..5ebfc756ebb 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/CatalogMetaData.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/CatalogMetaData.java @@ -44,7 +44,6 @@ import com.apple.foundationdb.relational.util.Assert; import com.google.protobuf.Descriptors; -import javax.annotation.Nonnull; import java.net.URI; import java.sql.DatabaseMetaData; import java.sql.SQLException; @@ -70,7 +69,6 @@ public CatalogMetaData(EmbeddedRelationalConnection conn, StoreCatalog catalog) this.conn = conn; } - @Nonnull @Override public RelationalResultSet getSchemas() throws SQLException { return getSchemas(conn.getPath().getPath(), null); @@ -103,7 +101,6 @@ public RelationalResultSet getSchemas(String catalogStr, String schemaPattern) t }); } - @Nonnull @Override public RelationalResultSet getTables(String database, String schema, String tableName, String[] types) throws SQLException { /* @@ -175,7 +172,6 @@ public RelationalResultSet getPrimaryKeys(String database, String schema, String }); } - @Nonnull @Override @SuppressWarnings("PMD.PreserveStackTrace") //we actually can't here, it will violate RecordLayer isolation laws public RelationalResultSet getColumns(String database, String schema, String tablePattern, String columnPattern) throws SQLException { @@ -338,8 +334,7 @@ public RelationalResultSet getIndexInfo(String database, String schema, String t }); } - @Nonnull - private RecordMetaDataProto.MetaData loadSchemaMetadata(@Nonnull final String database, @Nonnull final String schema) throws RelationalException { + private RecordMetaDataProto.MetaData loadSchemaMetadata(final String database, final String schema) throws RelationalException { final var recLayerSchema = this.catalog.loadSchema(conn.getTransaction(), URI.create(database), schema); Assert.thatUnchecked(recLayerSchema instanceof RecordLayerSchema); return (recLayerSchema.getSchemaTemplate().unwrap(RecordLayerSchemaTemplate.class).toRecordMetadata().toProto()); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ContinuationBuilder.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ContinuationBuilder.java index fe8ccc031c1..c6171f8cde8 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ContinuationBuilder.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ContinuationBuilder.java @@ -29,7 +29,6 @@ import com.apple.foundationdb.relational.continuation.CopyPlan; import com.google.protobuf.ByteString; -import javax.annotation.Nonnull; /** * A Builder class for an implementation of a {@link com.apple.foundationdb.relational.api.Continuation}. @@ -38,49 +37,42 @@ */ @API(API.Status.EXPERIMENTAL) public class ContinuationBuilder { - @Nonnull private final ContinuationProto.Builder proto; public ContinuationBuilder() { this.proto = ContinuationProto.newBuilder(); } - public ContinuationBuilder(@Nonnull ContinuationProto proto) { + public ContinuationBuilder(ContinuationProto proto) { this.proto = proto.toBuilder(); } - @Nonnull public ContinuationBuilder withExecutionState(byte[] executionState) { this.proto.setExecutionState(ByteString.copyFrom(executionState)); return this; } - @Nonnull public ContinuationBuilder withBindingHash(int hash) { proto.setBindingHash(hash); return this; } - @Nonnull public ContinuationBuilder withPlanHash(int hash) { proto.setPlanHash(hash); return this; } - @Nonnull - public ContinuationBuilder withCompiledStatement(@Nonnull final CompiledStatement compiledStatementProto) { + public ContinuationBuilder withCompiledStatement(final CompiledStatement compiledStatementProto) { proto.setCompiledStatement(compiledStatementProto); return this; } - @Nonnull - public ContinuationBuilder withCopyPlan(@Nonnull final CopyPlan copyPlan) { + public ContinuationBuilder withCopyPlan(final CopyPlan copyPlan) { proto.setCopyPlan(copyPlan); return this; } - @Nonnull - public ContinuationBuilder withReason(@Nonnull final Continuation.Reason reason) { + public ContinuationBuilder withReason(final Continuation.Reason reason) { proto.setReason(ContinuationProto.Reason.valueOf(reason.name())); return this; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ContinuationImpl.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ContinuationImpl.java index 5ac0653381f..55177a83b10 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ContinuationImpl.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ContinuationImpl.java @@ -34,8 +34,7 @@ import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.Locale; import java.util.Objects; @@ -47,7 +46,6 @@ public final class ContinuationImpl implements Continuation { public static final ContinuationImpl END = new ContinuationImpl(new byte[0]); - @Nonnull private final ContinuationProto proto; // TODO(yhatem) remove semantic nulls. @@ -59,7 +57,7 @@ private ContinuationImpl(@Nullable byte[] continuationBytes) { proto = builder.build(); } - ContinuationImpl(@Nonnull ContinuationProto proto) { + ContinuationImpl(ContinuationProto proto) { this.proto = proto; } @@ -98,7 +96,6 @@ public boolean hasCopyPlan() { return proto.hasCopyPlan(); } - @Nonnull public CopyPlan getCopyPlan() { return proto.getCopyPlan(); } @@ -200,7 +197,7 @@ public static ContinuationImpl parseContinuation(byte[] bytes) throws InvalidPro } } - public static ContinuationImpl copyOf(@Nonnull Continuation other) throws RelationalException { + public static ContinuationImpl copyOf(Continuation other) throws RelationalException { if (other instanceof ContinuationImpl) { // ContinuationImpl is immutable, no need to actually copy return (ContinuationImpl) other; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/DirectScannable.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/DirectScannable.java index 1d1bf75caec..97f416bc4a6 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/DirectScannable.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/DirectScannable.java @@ -26,8 +26,7 @@ import com.apple.foundationdb.relational.api.Transaction; import com.apple.foundationdb.relational.api.exceptions.RelationalException; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; public interface DirectScannable { @@ -52,9 +51,9 @@ public interface DirectScannable { */ ResumableIterator openScan( @Nullable Row keyPrefix, - @Nonnull Options options) throws RelationalException; + Options options) throws RelationalException; - Row get(@Nonnull Transaction t, @Nonnull Row key, @Nonnull Options options) throws RelationalException; + Row get(Transaction t, Row key, Options options) throws RelationalException; KeyBuilder getKeyBuilder() throws RelationalException; @@ -63,7 +62,6 @@ ResumableIterator openScan( * * @return the table name if it is a table, or index name if it is an index */ - @Nonnull String getName(); StructMetaData getMetaData() throws RelationalException; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalConnection.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalConnection.java index be2e7ff0070..a1e037d5d0a 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalConnection.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalConnection.java @@ -53,8 +53,7 @@ import com.apple.foundationdb.relational.util.Supplier; import com.google.common.annotations.VisibleForTesting; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.net.URI; import java.sql.Array; import java.sql.Connection; @@ -89,9 +88,7 @@ public class EmbeddedRelationalConnection implements RelationalConnection { private static final int DEFAULT_TRANSACTION_LEVEL = Connection.TRANSACTION_SERIALIZABLE; private boolean isClosed; - @Nonnull private final AbstractDatabase frl; - @Nonnull private final StoreCatalog backingCatalog; @Nullable private MetricCollector metricCollector; @@ -103,16 +100,15 @@ public class EmbeddedRelationalConnection implements RelationalConnection { private final boolean usingAnExternalTransaction; private final TransactionManager txnManager; - @Nonnull private Options options; private int transactionIsolation; @SpotBugsSuppressWarnings(value = "CT_CONSTRUCTOR_THROW", justification = "May be refactored as embedded takes over transaction lifetime") - public EmbeddedRelationalConnection(@Nonnull AbstractDatabase frl, - @Nonnull StoreCatalog backingCatalog, + public EmbeddedRelationalConnection(AbstractDatabase frl, + StoreCatalog backingCatalog, @Nullable Transaction transaction, - @Nonnull Options options) throws InternalErrorException { + Options options) throws InternalErrorException { this.frl = frl; this.txnManager = frl.getTransactionManager(); this.transaction = transaction; @@ -257,7 +253,7 @@ void setSchema(@Nullable String schema, boolean checkSchemaExists) throws SQLExc this.currentSchemaLabel = schema; } - private void checkSchemaExists(@Nonnull String schema) throws SQLException { + private void checkSchemaExists(String schema) throws SQLException { runIsolatedInTransactionIfPossible(() -> { if (!this.backingCatalog.doesSchemaExist(getTransaction(), getRecordLayerDatabase().getURI(), schema)) { throw new RelationalException(String.format(Locale.ROOT, "Schema %s does not exist in %s", schema, getPath()), ErrorCode.UNDEFINED_SCHEMA); @@ -266,7 +262,6 @@ private void checkSchemaExists(@Nonnull String schema) throws SQLException { }); } - @Nonnull public SchemaTemplate getSchemaTemplate() throws RelationalException { try { return backingCatalog.loadSchema(getTransaction(), getPath(), getSchema()).getSchemaTemplate(); @@ -316,7 +311,6 @@ public boolean isClosed() throws SQLException { return isClosed; } - @Nonnull @Override public RelationalDatabaseMetaData getMetaData() throws SQLException { return new CatalogMetaData(this, this.backingCatalog) { @@ -407,7 +401,6 @@ private void startTransaction() throws SQLException { } } - @Nonnull @Override public Options getOptions() { return options; @@ -425,7 +418,6 @@ public URI getPath() { return getRecordLayerDatabase().getURI(); } - @Nonnull public StoreCatalog getBackingCatalog() { return backingCatalog; } @@ -436,7 +428,6 @@ public StoreCatalog getBackingCatalog() { * @return the current transaction. * @throws RelationalException if there is no active transaction. */ - @Nonnull public Transaction getTransaction() throws RelationalException { if (transaction == null) { throw new RelationalException("No Active Transaction!", ErrorCode.INVALID_TRANSACTION_STATE); @@ -455,11 +446,10 @@ boolean inActiveTransaction() { return transaction != null; } - void addCloseListener(@Nonnull Runnable closeListener) throws RelationalException { + void addCloseListener(Runnable closeListener) throws RelationalException { this.transaction.unwrap(RecordContextTransaction.class).addTerminationListener(closeListener); } - @Nonnull public AbstractDatabase getRecordLayerDatabase() { return frl; } @@ -503,7 +493,6 @@ public void createNewTransaction() throws RelationalException, SQLException { ensureTransactionActive(); } - @Nonnull public ExecuteProperties getExecuteProperties() { return executeProperties; } @@ -533,19 +522,16 @@ private void checkOpen() throws SQLException { } } - @Nonnull @Override public T unwrap(Class iface) throws SQLException { return iface.cast(this); } - @Nonnull @Override public StatementBuilderFactory createStatementBuilderFactory() throws SQLException { return runIsolatedInTransactionIfPossible(() -> new StatementBuilderFactoryImpl(getSchemaTemplate(), this)); } - @Nonnull @Override public ExpressionFactory createExpressionBuilderFactory() throws SQLException { return runIsolatedInTransactionIfPossible(() -> new ExpressionFactoryImpl(getSchemaTemplate(), getOptions())); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalPreparedStatement.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalPreparedStatement.java index 2cb478c2c5f..3980053af8a 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalPreparedStatement.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalPreparedStatement.java @@ -33,7 +33,6 @@ import com.apple.foundationdb.relational.util.Assert; -import javax.annotation.Nonnull; import java.sql.Array; import java.sql.SQLException; import java.util.Locale; @@ -43,14 +42,11 @@ @API(API.Status.EXPERIMENTAL) public class EmbeddedRelationalPreparedStatement extends AbstractEmbeddedStatement implements RelationalPreparedStatement { - @Nonnull private final String sql; - @Nonnull private final Map parameters = new TreeMap<>(); - @Nonnull private final Map namedParameters = new TreeMap<>(); - public EmbeddedRelationalPreparedStatement(@Nonnull String sql, @Nonnull EmbeddedRelationalConnection conn) throws SQLException { + public EmbeddedRelationalPreparedStatement(String sql, EmbeddedRelationalConnection conn) throws SQLException { super(conn); this.sql = sql; } @@ -216,8 +212,7 @@ public void setNull(String parameterName, int sqlType) throws SQLException { } @Override - @Nonnull - PlanContext createPlanContext(@Nonnull final FDBRecordStoreBase store, @Nonnull final Options options) throws RelationalException { + PlanContext createPlanContext(final FDBRecordStoreBase store, final Options options) throws RelationalException { return PlanContext.builder() .fromRecordStore(store, options) .fromDatabase(conn.getRecordLayerDatabase()) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalStatement.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalStatement.java index 742bf08f945..17e04b135f8 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalStatement.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalStatement.java @@ -39,8 +39,7 @@ import com.apple.foundationdb.relational.util.Assert; import com.apple.foundationdb.relational.util.Supplier; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.sql.SQLException; import java.util.Collections; import java.util.Iterator; @@ -52,13 +51,12 @@ @API(API.Status.EXPERIMENTAL) public class EmbeddedRelationalStatement extends AbstractEmbeddedStatement implements RelationalStatement { - public EmbeddedRelationalStatement(@Nonnull EmbeddedRelationalConnection conn) throws SQLException { + public EmbeddedRelationalStatement(EmbeddedRelationalConnection conn) throws SQLException { super(conn); } @Override - @Nonnull - PlanContext createPlanContext(@Nonnull final FDBRecordStoreBase store, @Nonnull final Options options) throws RelationalException { + PlanContext createPlanContext(final FDBRecordStoreBase store, final Options options) throws RelationalException { return PlanContext.builder() .fromRecordStore(store, options) .fromDatabase(conn.getRecordLayerDatabase()) @@ -105,9 +103,8 @@ public int getUpdateCount() throws SQLException { } @Override - @Nonnull @SuppressWarnings("PMD.CloseResource") // lifetimes are more complicated; perhaps we should be closing - public RelationalResultSet executeScan(@Nonnull String tableName, @Nonnull KeySet prefix, @Nonnull Options options) throws SQLException { + public RelationalResultSet executeScan(String tableName, KeySet prefix, Options options) throws SQLException { checkOpen(); final var finalOptions = this.options.withChild(options); try { @@ -132,8 +129,7 @@ public RelationalResultSet executeScan(@Nonnull String tableName, @Nonnull KeySe } @Override - public @Nonnull - RelationalResultSet executeGet(@Nonnull String tableName, @Nonnull KeySet key, @Nonnull Options options) throws SQLException { + public RelationalResultSet executeGet(String tableName, KeySet key, Options options) throws SQLException { checkOpen(); final var finalizedOptions = this.options.withChild(options); return ensureTransaction(() -> { @@ -157,7 +153,7 @@ RelationalResultSet executeGet(@Nonnull String tableName, @Nonnull KeySet key, @ } @Override - public int executeInsert(@Nonnull String tableName, @Nonnull List data, @Nonnull final Options options) + public int executeInsert(String tableName, List data, final Options options) throws SQLException { checkOpen(); final var finalizedOptions = this.options.withChild(options); @@ -186,7 +182,7 @@ public int executeInsert(@Nonnull String tableName, @Nonnull List keys, @Nonnull Options options) throws SQLException { + public int executeDelete(String tableName, Iterator keys, Options options) throws SQLException { checkOpen(); if (!keys.hasNext()) { return 0; @@ -217,7 +213,7 @@ public int executeDelete(@Nonnull String tableName, @Nonnull Iterator ke @Override @SuppressWarnings("PMD.PreserveStackTrace") // intentional - Fall back for Invalid Range Exception from Record Layer - public void executeDeleteRange(@Nonnull String tableName, @Nonnull KeySet prefix, @Nonnull Options options) throws SQLException { + public void executeDeleteRange(String tableName, KeySet prefix, Options options) throws SQLException { checkOpen(); final var finalizedOptions = this.options.withChild(options); ensureTransaction(() -> { @@ -277,7 +273,7 @@ private void validateBindingHash(@Nullable ContinuationImpl continuation) throws // TODO (yhatem) this should be refactored and cleaned up, ideally consumers should work with structured metadata API // instead of this string processing since that is error-prone and somewhat very low-level. - private String[] getSchemaAndTable(@Nonnull EmbeddedRelationalConnection connection, @Nonnull String tableName) throws RelationalException { + private String[] getSchemaAndTable(EmbeddedRelationalConnection connection, String tableName) throws RelationalException { try { String schema = connection.getSchema(); String tableN = tableName; @@ -297,7 +293,7 @@ private String[] getSchemaAndTable(@Nonnull EmbeddedRelationalConnection connect } @SuppressWarnings("PMD.CloseResource") // lifetimes are more complicated; perhaps we should be closing - private @Nonnull DirectScannable getSourceScannable(String indexName, @Nonnull Table table) throws RelationalException { + private DirectScannable getSourceScannable(String indexName, Table table) throws RelationalException { if (indexName != null) { Index index = null; final Set readableIndexes = table.getAvailableIndexes(); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ErrorCapturingResultSet.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ErrorCapturingResultSet.java index ed490b709b5..28346116652 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ErrorCapturingResultSet.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ErrorCapturingResultSet.java @@ -28,7 +28,6 @@ import com.apple.foundationdb.relational.api.RelationalStruct; import com.apple.foundationdb.relational.recordlayer.util.ExceptionUtil; -import javax.annotation.Nonnull; import java.sql.SQLException; import java.util.UUID; @@ -257,7 +256,6 @@ public boolean isClosed() throws SQLException { return delegate.isClosed(); } - @Nonnull @Override public Continuation getContinuation() throws SQLException { try { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/FDBTuple.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/FDBTuple.java index b54f66c31ae..30f08c1c813 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/FDBTuple.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/FDBTuple.java @@ -26,7 +26,6 @@ import com.apple.foundationdb.relational.api.exceptions.InvalidTypeException; import com.apple.foundationdb.relational.api.exceptions.RelationalException; -import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -100,8 +99,7 @@ public String toString() { * * @param copy the tuple to copy */ - @Nonnull - public static FDBTuple fromRow(@Nonnull Row copy) throws RelationalException { + public static FDBTuple fromRow(Row copy) throws RelationalException { List items = new ArrayList<>(copy.getNumFields()); for (int i = 0; i < copy.getNumFields(); i++) { items.add(copy.getObject(i)); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/HollowTransactionManager.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/HollowTransactionManager.java index cdb9a1970c6..213347fac23 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/HollowTransactionManager.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/HollowTransactionManager.java @@ -27,14 +27,13 @@ import com.apple.foundationdb.relational.api.exceptions.OperationUnsupportedException; import com.apple.foundationdb.relational.api.exceptions.RelationalException; -import javax.annotation.Nonnull; @API(API.Status.EXPERIMENTAL) public class HollowTransactionManager implements TransactionManager { public static final HollowTransactionManager INSTANCE = new HollowTransactionManager(); @Override - public Transaction createTransaction(@Nonnull Options options) throws RelationalException { + public Transaction createTransaction(Options options) throws RelationalException { throw new OperationUnsupportedException("This Transaction manager is hollow and does not support calls."); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ImmutableKeyValue.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ImmutableKeyValue.java index 3e20fe5da6e..3da5a353490 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ImmutableKeyValue.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ImmutableKeyValue.java @@ -25,14 +25,13 @@ import com.apple.foundationdb.relational.api.Row; import com.apple.foundationdb.relational.api.exceptions.InvalidColumnReferenceException; -import javax.annotation.Nonnull; @API(API.Status.EXPERIMENTAL) public class ImmutableKeyValue extends AbstractRow { private final Row key; private final Row value; - public ImmutableKeyValue(@Nonnull Row key, @Nonnull Row value) { + public ImmutableKeyValue(Row key, Row value) { this.key = key; this.value = value; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/IteratorResultSet.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/IteratorResultSet.java index 925e2d4005d..0e15223cbfe 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/IteratorResultSet.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/IteratorResultSet.java @@ -27,7 +27,6 @@ import com.apple.foundationdb.relational.api.exceptions.RelationalException; import com.apple.foundationdb.relational.util.SpotBugsSuppressWarnings; -import javax.annotation.Nonnull; import java.sql.SQLException; import java.util.Iterator; @@ -51,7 +50,6 @@ public IteratorResultSet(StructMetaData metaData, Iterator rowIte this.currentRowPosition = initialRowPosition; } - @Nonnull @Override public Continuation getContinuation() throws SQLException { boolean hasNext = rowIter.hasNext(); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/KeyBuilder.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/KeyBuilder.java index a29e383cba1..ea91338c998 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/KeyBuilder.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/KeyBuilder.java @@ -40,7 +40,6 @@ import com.google.common.base.Joiner; -import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -65,7 +64,6 @@ public int getKeySize() { return key.getColumnSize(); } - @Nonnull public Row buildKey(Map keyFields, boolean failOnIncompleteKey) throws RelationalException { Map keysNotPicked = new HashMap<>(keyFields); List flattenedFields = new ArrayList<>(); @@ -107,7 +105,6 @@ public Row buildKey(Map keyFields, boolean failOnIncompleteKey) return new FDBTuple(Tuple.fromList(flattenedFields)); } - @Nonnull public Row buildKey(Row scannedRow) throws RelationalException { int scannedIndex = 0; List flattenedFields = new ArrayList<>(); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/KeySpaceUtils.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/KeySpaceUtils.java index a3a14864448..a58b926e908 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/KeySpaceUtils.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/KeySpaceUtils.java @@ -31,8 +31,7 @@ import com.apple.foundationdb.relational.api.exceptions.RelationalException; import com.google.common.collect.Lists; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.net.URI; import java.util.Arrays; import java.util.List; @@ -43,13 +42,11 @@ @API(API.Status.EXPERIMENTAL) public final class KeySpaceUtils { - @Nonnull - public static URI pathToUri(@Nonnull KeySpacePath dbPath) { + public static URI pathToUri(KeySpacePath dbPath) { return URI.create(pathToUriList(dbPath).stream().collect(Collectors.joining("/", "/", ""))); } - @Nonnull - private static List pathToUriList(final @Nonnull KeySpacePath dbPath) { + private static List pathToUriList(final KeySpacePath dbPath) { return Lists.reverse( Stream.iterate(dbPath, Objects::nonNull, KeySpacePath::getParent) .map(KeySpaceUtils::toPathElement) @@ -69,8 +66,7 @@ public static String toPathString(KeySpacePath path) { } @API(API.Status.INTERNAL) - @Nonnull - public static KeySpacePath toKeySpacePath(@Nonnull URI url, @Nonnull KeySpace keySpace) throws RelationalException { + public static KeySpacePath toKeySpacePath(URI url, KeySpace keySpace) throws RelationalException { String path = getPath(url); if (path.length() < 1) { throw new RelationalException("<" + url + "> is an invalid database path", ErrorCode.INVALID_PATH); @@ -99,7 +95,7 @@ public static KeySpacePath toKeySpacePath(@Nonnull URI url, @Nonnull KeySpace ke return thePath; } - public static String getPath(@Nonnull URI url) { + public static String getPath(URI url) { String authority = url.getAuthority(); return authority != null && authority.length() > 0 ? "//" + authority + url.getPath() : url.getPath(); } @@ -108,11 +104,11 @@ public static String getPath(@Nonnull URI url) { /*private helper methods*/ @Nullable - private static KeySpacePath matchPathToSubdirectories(final @Nonnull KeySpace keySpace, + private static KeySpacePath matchPathToSubdirectories(final KeySpace keySpace, final @Nullable KeySpacePath parentPath, - final @Nonnull List subdirectories, - final @Nonnull URI url, - final @Nonnull String[] pathElems, + final List subdirectories, + final URI url, + final String[] pathElems, final int position) throws RelationalException { KeySpacePath thePath = null; for (KeySpaceDirectory dir : subdirectories) { @@ -133,11 +129,11 @@ private static KeySpacePath matchPathToSubdirectories(final @Nonnull KeySpace ke @Nullable @SuppressWarnings("PMD.CompareObjectsWithEquals") - private static KeySpacePath matchPathToDirectory(final @Nonnull KeySpace keySpace, - final @Nonnull KeySpaceDirectory directory, + private static KeySpacePath matchPathToDirectory(final KeySpace keySpace, + final KeySpaceDirectory directory, final @Nullable KeySpacePath parentPath, - final @Nonnull URI url, - final @Nonnull String[] pathElems, + final URI url, + final String[] pathElems, final int position) throws RelationalException { if (position >= pathElems.length) { throw new RelationalException("path is too deep", ErrorCode.INTERNAL_ERROR) @@ -195,7 +191,7 @@ private static KeySpacePath matchPathToDirectory(final @Nonnull KeySpace keySpac } @Nullable - private static String matchPathElementToString(final @Nonnull KeySpaceDirectory directory, final String pathElem) throws RelationalException { + private static String matchPathElementToString(final KeySpaceDirectory directory, final String pathElem) throws RelationalException { // the empty string maps to null, and cannot be a string if (directory.isConstant() && !Objects.equals(getConstantValue(directory), pathElem)) { return null; @@ -206,7 +202,7 @@ private static String matchPathElementToString(final @Nonnull KeySpaceDirectory } @Nullable - private static Object matchPathElementToLong(final @Nonnull KeySpaceDirectory directory, final String pathElem) throws RelationalException { + private static Object matchPathElementToLong(final KeySpaceDirectory directory, final String pathElem) throws RelationalException { Long parsedLong = tryParseLong(pathElem); if (parsedLong == null) { return null; @@ -238,7 +234,7 @@ private static Long tryParseLong(final String pathElem) { } @Nullable - private static Object getConstantValue(final @Nonnull KeySpaceDirectory directory) throws RelationalException { + private static Object getConstantValue(final KeySpaceDirectory directory) throws RelationalException { Object dirVal = directory.getValue(); if ("".equals(dirVal)) { throw new RelationalException("Directory contains constant empty string (\"\")", ErrorCode.INVALID_PATH) @@ -248,7 +244,7 @@ private static Object getConstantValue(final @Nonnull KeySpaceDirectory director } @Nullable - private static KeySpacePath getSubPath(final @Nonnull KeySpace keySpace, final @Nullable KeySpacePath parentPath, final String pathName, final Object pathValue) { + private static KeySpacePath getSubPath(final KeySpace keySpace, final @Nullable KeySpacePath parentPath, final String pathName, final Object pathValue) { try { if (parentPath == null) { return keySpace.path(pathName, pathValue); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/MessageTuple.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/MessageTuple.java index e29bef59487..f9f9e109486 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/MessageTuple.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/MessageTuple.java @@ -32,7 +32,6 @@ import com.google.protobuf.Descriptors; import com.google.protobuf.Message; -import javax.annotation.Nonnull; import java.util.List; import java.util.stream.Collectors; @@ -77,7 +76,7 @@ public Object getObject(int position) throws InvalidColumnReferenceException { } } - public static Object sanitizeField(@Nonnull final Object field, @Nonnull final DescriptorProtos.FieldOptions fieldOptions) { + public static Object sanitizeField(final Object field, final DescriptorProtos.FieldOptions fieldOptions) { if (field instanceof Message && ((Message) field).getDescriptorForType().equals(TupleFieldsProto.UUID.getDescriptor())) { return TupleFieldsHelper.fromProto((Message) field, TupleFieldsProto.UUID.getDescriptor()); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/QueryExecutor.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/QueryExecutor.java index d5108d1c100..d137aedb549 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/QueryExecutor.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/QueryExecutor.java @@ -34,8 +34,7 @@ import com.apple.foundationdb.relational.api.exceptions.RelationalException; import com.apple.foundationdb.relational.util.Assert; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; /** * A query executor that executes a plan and returns its results. @@ -46,18 +45,17 @@ public class QueryExecutor { private final RecordQueryPlan plan; private final EvaluationContext evaluationContext; - public QueryExecutor(@Nonnull final RecordQueryPlan plan, - @Nonnull final EvaluationContext evaluationContext, - @Nonnull final RecordLayerSchema schema) { + public QueryExecutor(final RecordQueryPlan plan, + final EvaluationContext evaluationContext, + final RecordLayerSchema schema) { this.schema = schema; this.evaluationContext = evaluationContext; this.plan = plan; } @SuppressWarnings("PMD.CloseResource") // cursor lifetime continues with iterator - @Nonnull public ResumableIterator execute(@Nullable final Continuation continuation, - @Nonnull final ExecuteProperties executeProperties) throws RelationalException { + final ExecuteProperties executeProperties) throws RelationalException { final FDBRecordStoreBase fdbRecordStore = Assert.notNull(schema.loadStore()).unwrap(FDBRecordStoreBase.class); final RecordCursor cursor = plan.executePlan(fdbRecordStore, evaluationContext, diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/QueryPropertiesUtils.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/QueryPropertiesUtils.java index cf67eccab99..0adfc2c20cc 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/QueryPropertiesUtils.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/QueryPropertiesUtils.java @@ -26,11 +26,10 @@ import com.apple.foundationdb.record.ScanProperties; import com.apple.foundationdb.relational.api.Options; -import javax.annotation.Nonnull; @API(API.Status.EXPERIMENTAL) public final class QueryPropertiesUtils { - static ExecuteProperties getExecuteProperties(@Nonnull Options options) { + static ExecuteProperties getExecuteProperties(Options options) { ExecuteProperties.Builder builder = ExecuteProperties.newBuilder(); Integer rowLimit = options.getOption(Options.Name.MAX_ROWS); if (rowLimit != null) { @@ -39,7 +38,7 @@ static ExecuteProperties getExecuteProperties(@Nonnull Options options) { return builder.build(); } - public static ScanProperties getScanProperties(@Nonnull Options options) { + public static ScanProperties getScanProperties(Options options) { ExecuteProperties executeProperties = getExecuteProperties(options); return new ScanProperties(executeProperties); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordContextTransaction.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordContextTransaction.java index 12da4d11f95..ed40f74c12f 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordContextTransaction.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordContextTransaction.java @@ -33,7 +33,6 @@ import com.apple.foundationdb.relational.api.metadata.SchemaTemplate; import com.apple.foundationdb.relational.recordlayer.util.ExceptionUtil; -import javax.annotation.Nonnull; import java.util.LinkedList; import java.util.List; import java.util.Optional; @@ -83,14 +82,13 @@ public void abort() throws RelationalException { } } - @Nonnull @Override public Optional getBoundSchemaTemplateMaybe() { return Optional.ofNullable(context.getInSession(SchemaTemplate.class.toString(), SchemaTemplate.class)); } @Override - public void setBoundSchemaTemplate(@Nonnull final SchemaTemplate schemaTemplate) { + public void setBoundSchemaTemplate(final SchemaTemplate schemaTemplate) { unsetBoundSchemaTemplate(); context.putInSessionIfAbsent(SchemaTemplate.class.toString(), schemaTemplate); } @@ -110,9 +108,8 @@ public boolean isClosed() { return isClosed; } - @Nonnull @Override - public T unwrap(@Nonnull Class type) throws InternalErrorException { + public T unwrap(Class type) throws InternalErrorException { if (FDBRecordContext.class.isAssignableFrom(type)) { return type.cast(context); } @@ -125,7 +122,7 @@ private void notifyTerminated() { } } - public void addTerminationListener(@Nonnull Runnable onTerminateListener) { + public void addTerminationListener(Runnable onTerminateListener) { assert !isClosed : "Cannot add a termination listener to a closed transaction!"; txnTerminateListeners.add(onTerminateListener); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerDatabase.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerDatabase.java index cca2dbb5217..429c3329700 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerDatabase.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerDatabase.java @@ -38,8 +38,7 @@ import com.apple.foundationdb.relational.recordlayer.storage.BackingRecordStore; import com.apple.foundationdb.relational.recordlayer.storage.StoreConfig; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import javax.annotation.concurrent.NotThreadSafe; import java.net.URI; import java.sql.SQLException; @@ -76,11 +75,11 @@ public RecordLayerDatabase(FdbConnection fdbDb, StoreCatalog storeCatalog, RecordLayerConfig config, RelationalKeyspaceProvider.RelationalDatabasePath databasePath, - @Nonnull final MetadataOperationsFactory metadataOperationsFactory, - @Nonnull final DdlQueryFactory ddlQueryFactory, + final MetadataOperationsFactory metadataOperationsFactory, + final DdlQueryFactory ddlQueryFactory, @Nullable RelationalPlanCache planCache, @Nullable String defaultSchema, - @Nonnull Options options) { + Options options) { super(metadataOperationsFactory, ddlQueryFactory, planCache, options); this.fdbDb = fdbDb; this.metaDataStore = new CachedMetaDataStore(metaDataStore); @@ -125,7 +124,7 @@ public void close() throws RelationalException { schemas.clear(); } - BackingRecordStore loadStore(@Nonnull Transaction txn, @Nonnull String schemaName, @Nonnull FDBRecordStoreBase.StoreExistenceCheck existenceCheck) throws RelationalException { + BackingRecordStore loadStore(Transaction txn, String schemaName, FDBRecordStoreBase.StoreExistenceCheck existenceCheck) throws RelationalException { StoreConfig storeConfig = StoreConfig.create(recordLayerConfig, schemaName, databasePath, metaDataStore, txn, options); return BackingRecordStore.load(txn, storeConfig, existenceCheck); } @@ -138,7 +137,7 @@ FdbConnection getFDBDatabase() { /* private helper methods */ @Override - public BackingRecordStore loadRecordStore(@Nonnull String schemaId, @Nonnull FDBRecordStoreBase.StoreExistenceCheck existenceCheck) throws RelationalException { + public BackingRecordStore loadRecordStore(String schemaId, FDBRecordStoreBase.StoreExistenceCheck existenceCheck) throws RelationalException { return loadStore(getCurrentTransaction(), schemaId, existenceCheck); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerEngine.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerEngine.java index e3f962f21a6..459944c4460 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerEngine.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerEngine.java @@ -40,8 +40,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; @@ -51,12 +50,12 @@ public final class RecordLayerEngine { private static final Logger logger = LogManager.getLogger(RecordLayerEngine.class); - public static EmbeddedRelationalEngine makeEngine(@Nonnull RecordLayerConfig cfg, - @Nonnull List databases, - @Nonnull KeySpace baseKeySpace, - @Nonnull StoreCatalog schemaCatalog, + public static EmbeddedRelationalEngine makeEngine(RecordLayerConfig cfg, + List databases, + KeySpace baseKeySpace, + StoreCatalog schemaCatalog, @Nullable MetricRegistry metricsEngine, - @Nonnull RecordLayerMetadataOperationsFactory ddlFactory, + RecordLayerMetadataOperationsFactory ddlFactory, @Nullable RelationalPlanCache planCache) { MetricRegistry mEngine = convertToRecordLayerEngine(metricsEngine); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerIterator.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerIterator.java index e5efedaa64b..2f563dc674e 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerIterator.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerIterator.java @@ -31,8 +31,7 @@ import com.apple.foundationdb.relational.api.exceptions.RelationalException; import com.apple.foundationdb.relational.recordlayer.util.ExceptionUtil; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.function.Function; @API(API.Status.EXPERIMENTAL) @@ -43,7 +42,7 @@ public final class RecordLayerIterator implements ResumableIterator { private Continuation continuation; private RecordCursor.NoNextReason noNextReason = null; - private RecordLayerIterator(@Nonnull RecordCursor cursor, @Nonnull Function transform) throws RelationalException { + private RecordLayerIterator(RecordCursor cursor, Function transform) throws RelationalException { this.recordCursor = cursor; this.transform = transform; // TODO(sfines,yhatem) perform this in a non-blocking manner for more efficiency. diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerResultSet.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerResultSet.java index c8696f5b749..f559af26b8b 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerResultSet.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerResultSet.java @@ -29,8 +29,7 @@ import com.apple.foundationdb.relational.api.exceptions.UncheckedRelationalException; import com.apple.foundationdb.relational.api.exceptions.RelationalException; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.sql.SQLException; import static com.apple.foundationdb.relational.api.exceptions.ErrorCode.UNSUPPORTED_OPERATION; @@ -38,7 +37,6 @@ @API(API.Status.EXPERIMENTAL) public class RecordLayerResultSet extends AbstractRecordLayerResultSet { - @Nonnull private final ResumableIterator currentCursor; // needed until TODO is fixed @@ -49,19 +47,18 @@ public class RecordLayerResultSet extends AbstractRecordLayerResultSet { private volatile boolean closed; - @Nonnull private final EnrichContinuationFunction enrichContinuationFunction; - public RecordLayerResultSet(@Nonnull StructMetaData metaData, - @Nonnull final ResumableIterator iterator, + public RecordLayerResultSet(StructMetaData metaData, + final ResumableIterator iterator, @Nullable final EmbeddedRelationalConnection connection) { this(metaData, iterator, connection, EnrichContinuationFunction.identity()); } - public RecordLayerResultSet(@Nonnull StructMetaData metaData, - @Nonnull final ResumableIterator iterator, + public RecordLayerResultSet(StructMetaData metaData, + final ResumableIterator iterator, @Nullable final EmbeddedRelationalConnection connection, - @Nonnull final EnrichContinuationFunction enrichContinuationFunction) { + final EnrichContinuationFunction enrichContinuationFunction) { super(metaData); this.currentCursor = iterator; this.connection = connection; @@ -105,7 +102,6 @@ public boolean isClosed() throws SQLException { return this.closed; } - @Nonnull @Override public Continuation getContinuation() throws SQLException { if (hasNext()) { @@ -136,8 +132,7 @@ private Continuation.Reason continuationReason() { @FunctionalInterface public interface EnrichContinuationFunction { - @Nonnull - Continuation apply(@Nonnull Continuation continuation, Continuation.Reason reason) throws RelationalException; + Continuation apply(Continuation continuation, Continuation.Reason reason) throws RelationalException; static EnrichContinuationFunction identity() { return (continuation, reason) -> continuation; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerSchema.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerSchema.java index 8460a8c96d7..8f7aa884287 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerSchema.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerSchema.java @@ -30,7 +30,6 @@ import com.apple.foundationdb.relational.recordlayer.storage.BackingStore; import com.apple.foundationdb.relational.util.Assert; -import javax.annotation.Nonnull; import javax.annotation.concurrent.NotThreadSafe; import java.util.HashMap; import java.util.Map; @@ -42,7 +41,6 @@ public class RecordLayerSchema implements DatabaseSchema { private final AbstractDatabase db; //could be accessed through the database, but this seems convenient final EmbeddedRelationalConnection conn; - @Nonnull private final String schemaName; private final FDBRecordStoreBase.StoreExistenceCheck existenceCheck; @@ -55,22 +53,20 @@ public class RecordLayerSchema implements DatabaseSchema { */ private final Map loadedTables = new HashMap<>(); - public RecordLayerSchema(@Nonnull String schemaName, AbstractDatabase database, EmbeddedRelationalConnection connection) throws RelationalException { + public RecordLayerSchema(String schemaName, AbstractDatabase database, EmbeddedRelationalConnection connection) throws RelationalException { this.schemaName = schemaName; this.db = database; this.conn = connection; this.existenceCheck = FDBRecordStoreBase.StoreExistenceCheck.ERROR_IF_NOT_EXISTS; } - @Nonnull @Override public String getSchemaName() { return schemaName; } @SuppressWarnings("PMD.CloseResource") // false positive as resource not closed is null - @Nonnull - public Table loadTable(@Nonnull String tableName) throws RelationalException { + public Table loadTable(String tableName) throws RelationalException { //TODO(bfines) load the record type index, rather than just the generic type, then // return an index object instead RecordTypeTable t = loadedTables.get(tableName); @@ -95,7 +91,6 @@ public void close() throws RelationalException { loadedTables.clear(); } - @Nonnull public BackingStore loadStore() throws RelationalException { // loadStore() expects an active transaction which should be taken care by the caller. Assert.thatUnchecked(conn.inActiveTransaction(), ErrorCode.INTERNAL_ERROR, "No active transaction!"); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerStorageCluster.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerStorageCluster.java index 96dad859b40..01b74d307d9 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerStorageCluster.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerStorageCluster.java @@ -36,8 +36,7 @@ import com.apple.foundationdb.relational.recordlayer.ddl.RecordLayerMetadataOperationsFactory; import com.apple.foundationdb.relational.recordlayer.query.cache.RelationalPlanCache; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.net.URI; import java.util.Collections; import java.util.HashMap; @@ -99,8 +98,8 @@ private Map parseConnectionQueryString(@Nullable String queryStr @Override @Nullable - public RelationalDatabase loadDatabase(@Nonnull URI url, - @Nonnull Options connOptions) throws RelationalException { + public RelationalDatabase loadDatabase(URI url, + Options connOptions) throws RelationalException { Map connectionOptions = parseConnectionQueryString(url.getQuery()); String presetSchema = connectionOptions.get("SCHEMA"); try (Transaction txn = getTransactionManager().createTransaction(Options.NONE)) { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerTransactionManager.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerTransactionManager.java index 8cf472ece29..acdc4bc4e99 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerTransactionManager.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerTransactionManager.java @@ -32,7 +32,6 @@ import com.codahale.metrics.MetricRegistry; -import javax.annotation.Nonnull; @API(API.Status.EXPERIMENTAL) public class RecordLayerTransactionManager implements TransactionManager { @@ -45,7 +44,7 @@ public RecordLayerTransactionManager(FDBDatabase fdbDb, MetricRegistry metricReg } @Override - public Transaction createTransaction(@Nonnull Options connectionOptions) throws RelationalException { + public Transaction createTransaction(Options connectionOptions) throws RelationalException { return new RecordContextTransaction(fdbDb.openContext(getFDBRecordContextConfig(connectionOptions, metricRegistry))); } @@ -59,7 +58,7 @@ public void commit(Transaction txn) throws RelationalException { txn.commit(); } - private FDBRecordContextConfig getFDBRecordContextConfig(@Nonnull Options options, MetricRegistry metricRegistry) { + private FDBRecordContextConfig getFDBRecordContextConfig(Options options, MetricRegistry metricRegistry) { FDBRecordContextConfig.Builder builder = FDBRecordContextConfig.newBuilder() .setTimer(new MetricRegistryStoreTimer(metricRegistry)); Long transactionTimeout = options.getOption(Options.Name.TRANSACTION_TIMEOUT); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordStoreAndRecordContextTransaction.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordStoreAndRecordContextTransaction.java index c50a546c50f..560016d2833 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordStoreAndRecordContextTransaction.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordStoreAndRecordContextTransaction.java @@ -32,7 +32,6 @@ import com.google.protobuf.Message; -import javax.annotation.Nonnull; import java.util.Optional; /** @@ -71,14 +70,13 @@ public void abort() throws RelationalException { transaction.abort(); } - @Nonnull @Override public Optional getBoundSchemaTemplateMaybe() { return transaction.getBoundSchemaTemplateMaybe(); } @Override - public void setBoundSchemaTemplate(@Nonnull final SchemaTemplate schemaTemplate) { + public void setBoundSchemaTemplate(final SchemaTemplate schemaTemplate) { transaction.setBoundSchemaTemplate(schemaTemplate); } @@ -105,7 +103,6 @@ public FDBRecordStoreBase getRecordStore() { return store; } - @Nonnull public SchemaTemplate getBoundSchemaTemplate() { return boundSchemaTemplate; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordStoreIndex.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordStoreIndex.java index 5bfd630f58d..597eedbb84a 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordStoreIndex.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordStoreIndex.java @@ -41,8 +41,7 @@ import com.apple.foundationdb.relational.recordlayer.storage.BackingStore; import com.google.protobuf.Descriptors; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.List; import java.util.function.Function; @@ -62,7 +61,6 @@ public void validate(Options scanOptions) throws RelationalException { table.loadRecordType(scanOptions); } - @Nonnull @Override public String getName() { return index.getName(); @@ -88,7 +86,7 @@ public void close() throws RelationalException { } @Override - public Row get(@Nonnull Transaction t, @Nonnull Row key, @Nonnull Options options) throws RelationalException { + public Row get(Transaction t, Row key, Options options) throws RelationalException { BackingStore store = getSchema().loadStore(); return store.getFromIndex(index, key, options); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordTypeScannable.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordTypeScannable.java index e6e8c71d8e6..6f6cfeb9a6f 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordTypeScannable.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordTypeScannable.java @@ -28,8 +28,7 @@ import com.apple.foundationdb.relational.api.exceptions.RelationalException; import com.apple.foundationdb.relational.recordlayer.storage.BackingStore; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.function.Function; public abstract class RecordTypeScannable implements DirectScannable { @@ -38,7 +37,7 @@ public abstract class RecordTypeScannable implements DirectScannable { @Override public final ResumableIterator openScan( @Nullable Row keyPrefix, - @Nonnull Options options) throws RelationalException { + Options options) throws RelationalException { TupleRange range = TupleRange.allOf(TupleUtils.toFDBTuple(keyPrefix)); BackingStore store = getSchema().loadStore(); final RecordCursor cursor = openScan(store, range, options.getOption(Options.Name.CONTINUATION), options); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordTypeTable.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordTypeTable.java index 91fc45e8729..e2a6d2f7a6d 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordTypeTable.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordTypeTable.java @@ -57,8 +57,7 @@ import com.google.protobuf.DynamicMessage; import com.google.protobuf.Message; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.sql.SQLException; import java.util.List; import java.util.Locale; @@ -80,8 +79,8 @@ public class RecordTypeTable extends RecordTypeScannable prefix) throws RelationalException { @Override @Deprecated - public boolean insertRecord(@Nonnull Message message, boolean replaceOnDuplicate) throws RelationalException { + public boolean insertRecord(Message message, boolean replaceOnDuplicate) throws RelationalException { BackingStore store = schema.loadStore(); //TODO(bfines) maybe this should return something other than boolean? return store.insert(tableName, message, replaceOnDuplicate); @@ -169,7 +166,7 @@ public boolean insertRecord(@Nonnull Message message, boolean replaceOnDuplicate @Override @Deprecated @SuppressWarnings("PMD.PreserveStackTrace") //we are intentionally destroying the stack trace here - public boolean insertRecord(@Nonnull RelationalStruct insert, boolean replaceOnDuplicate) throws RelationalException { + public boolean insertRecord(RelationalStruct insert, boolean replaceOnDuplicate) throws RelationalException { BackingStore store = schema.loadStore(); try { final RecordType recordType = store.getRecordMetaData().getRecordType(this.tableName); @@ -185,7 +182,6 @@ public boolean insertRecord(@Nonnull RelationalStruct insert, boolean replaceOnD * This is used to support {@link com.apple.foundationdb.relational.api.RelationalDirectAccessStatement#executeInsert} operation and * should not be used for any other general purpose. */ - @Nonnull public static Message toDynamicMessage(RelationalStruct struct, Descriptors.Descriptor descriptor) throws RelationalException { DynamicMessage.Builder builder = DynamicMessage.newBuilder(descriptor); try { @@ -323,14 +319,13 @@ public void close() throws RelationalException { currentTypeRef = null; } - @Nonnull @Override public String getName() { return tableName; } @Override - public void validateTable(@Nonnull Options options) throws RelationalException { + public void validateTable(Options options) throws RelationalException { loadRecordType(options); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RelationalKeyspaceProvider.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RelationalKeyspaceProvider.java index ef82783624b..188d0bc7cab 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RelationalKeyspaceProvider.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RelationalKeyspaceProvider.java @@ -36,7 +36,6 @@ import com.apple.foundationdb.relational.util.Assert; import com.google.common.annotations.VisibleForTesting; -import javax.annotation.Nonnull; import java.net.URI; import java.util.concurrent.CompletableFuture; @@ -73,22 +72,19 @@ private RelationalKeyspaceProvider() { } public static class RelationalDomainPath extends KeySpacePathWrapper { - public RelationalDomainPath(@Nonnull KeySpacePath inner) { + public RelationalDomainPath(KeySpacePath inner) { super(inner); } - @Nonnull public String getDomainName() { return inner.getDirectoryName(); } - @Nonnull - public RelationalDatabasePath database(@Nonnull String dbName) { + public RelationalDatabasePath database(String dbName) { Assert.thatUnchecked(INTERNING_LAYER.equals(dbName), ErrorCode.INVALID_DATABASE, () -> "Invalid database name: " + dbName); return (RelationalDatabasePath) inner.add(DB_NAME_DIR, dbName); } - @Nonnull public KeySpacePath internedStrings() { return inner.add(INTERNING_LAYER); } @@ -100,8 +96,7 @@ public KeySpacePath internedStrings() { * @param context the FDB transaction context to use to resolve paths here * @return a future that will contain a {@link LocatableResolver} used by this domain */ - @Nonnull - public CompletableFuture generateScopeAsync(@Nonnull FDBRecordContext context) { + public CompletableFuture generateScopeAsync(FDBRecordContext context) { return internedStrings().toResolvedPathAsync(context) // Use ScopedInterningLayer here instead of a ScopedDirectoryLayer because it is more tailored to the job of shortening strings .thenApply(resolvedPath -> new ScopedInterningLayer(context.getDatabase(), resolvedPath)); @@ -114,12 +109,10 @@ public RelationalDatabasePath(KeySpacePath inner) { super(inner); } - @Nonnull public RelationalSchemaPath schemaPath(String schemaName) { return (RelationalSchemaPath) this.inner.add(RelationalKeyspaceProvider.SCHEMA_DIR, schemaName); } - @Nonnull public URI toUri() { return KeySpaceUtils.pathToUri(inner); } @@ -130,15 +123,13 @@ public RelationalSystemDomainPath(KeySpacePath inner) { super(inner); } - @Nonnull @Override public String getDomainName() { return SYS; } - @Nonnull @Override - public RelationalSystemDatabasePath database(@Nonnull String dbName) { + public RelationalSystemDatabasePath database(String dbName) { Assert.thatUnchecked(SYS.equals(dbName), ErrorCode.UNDEFINED_DATABASE, "Unknown system database name: " + dbName); return (RelationalSystemDatabasePath) super.database(dbName); } @@ -151,14 +142,12 @@ public RelationalSystemDatabasePath(KeySpacePath inner) { } @Override - @Nonnull public RelationalSchemaPath schemaPath(String schemaName) { Assert.thatUnchecked(CATALOG.equals(schemaName), ErrorCode.UNDEFINED_SCHEMA, "Unknown system schema name: " + schemaName); return (RelationalSchemaPath) inner.add(CATALOG); } @Override - @Nonnull public URI toUri() { return URI.create("/" + SYS); } @@ -188,7 +177,7 @@ private static KeySpaceDirectory getSystemDirectory() { .addSubdirectory(new KeySpaceDirectory(INTERNING_LAYER, KeySpaceDirectory.KeyType.STRING, INTERNING_LAYER_VALUE)); } - public void registerDomainIfNotExists(@Nonnull String domainName) { + public void registerDomainIfNotExists(String domainName) { final var keySpaceRoot = getKeySpace().getRoot(); final var exists = keySpaceRoot.getSubdirectories().stream() .map(KeySpaceDirectory::getName) @@ -214,11 +203,11 @@ public KeySpace getKeySpace() { return keyspace; } - public RelationalKeyspaceProvider.RelationalDatabasePath toDatabasePath(@Nonnull URI url) throws RelationalException { + public RelationalKeyspaceProvider.RelationalDatabasePath toDatabasePath(URI url) throws RelationalException { return toDatabasePath(url, getKeySpace()); } - public static RelationalKeyspaceProvider.RelationalDatabasePath toDatabasePath(@Nonnull URI url, KeySpace keyspace) throws RelationalException { + public static RelationalKeyspaceProvider.RelationalDatabasePath toDatabasePath(URI url, KeySpace keyspace) throws RelationalException { final var keySpacePath = KeySpaceUtils.toKeySpacePath(url, keyspace); // KeySpacePath is to the System database directory if (keySpacePath instanceof RelationalSystemDatabasePath) { @@ -231,13 +220,11 @@ public static RelationalKeyspaceProvider.RelationalDatabasePath toDatabasePath(@ throw new RelationalException("<" + url + "> is an invalid database path", ErrorCode.INVALID_PATH); } - @Nonnull public static RelationalKeyspaceProvider instance() { return INSTANCE; } @VisibleForTesting - @Nonnull public static RelationalKeyspaceProvider newInstanceForTesting() { return new RelationalKeyspaceProvider(); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/Table.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/Table.java index 6c0d973a32e..77abfa738a3 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/Table.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/Table.java @@ -29,7 +29,6 @@ import com.google.protobuf.Message; -import javax.annotation.Nonnull; import java.util.Map; import java.util.Set; @@ -37,7 +36,6 @@ @ConnectionScoped public interface Table extends DirectScannable, AutoCloseable { - @Nonnull DatabaseSchema getSchema(); //TODO(bfines) I'm not sure if this is the right place to put this logic @@ -46,7 +44,7 @@ public interface Table extends DirectScannable, AutoCloseable { // correct mutation behavior // and what about scans/gets? Should they go here too? - boolean deleteRecord(@Nonnull Row key) throws RelationalException; + boolean deleteRecord(Row key) throws RelationalException; void deleteRange(Map prefix) throws RelationalException; @@ -59,7 +57,7 @@ public interface Table extends DirectScannable, AutoCloseable { * @deprecated since 01/18/2023; use {@link #insertRecord(RelationalStruct, boolean)} instead. */ @Deprecated - boolean insertRecord(@Nonnull Message message, boolean replaceOnDuplicate) throws RelationalException; + boolean insertRecord(Message message, boolean replaceOnDuplicate) throws RelationalException; /** * Replaces {@link #insertRecord(Message, boolean)} encapsulating protobuf usage. @@ -68,14 +66,13 @@ public interface Table extends DirectScannable, AutoCloseable { * @return Whether insert was successful or not. * @throws RelationalException Thrown if record exists already or if error on insert. */ - boolean insertRecord(@Nonnull RelationalStruct insert, boolean replaceOnDuplicate) throws RelationalException; + boolean insertRecord(RelationalStruct insert, boolean replaceOnDuplicate) throws RelationalException; Set getAvailableIndexes() throws RelationalException; @Override void close() throws RelationalException; - @Nonnull @Override String getName(); @@ -88,5 +85,5 @@ public interface Table extends DirectScannable, AutoCloseable { * @param options the options to use. * @throws RelationalException if the table is invalid for these options. */ - void validateTable(@Nonnull Options options) throws RelationalException; + void validateTable(Options options) throws RelationalException; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/CachedMetaDataStore.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/CachedMetaDataStore.java index 48418a58a80..c7a4e4e77a6 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/CachedMetaDataStore.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/CachedMetaDataStore.java @@ -28,7 +28,6 @@ import com.apple.foundationdb.relational.api.exceptions.RelationalException; import com.apple.foundationdb.relational.recordlayer.RecordContextTransaction; -import javax.annotation.Nonnull; import javax.annotation.concurrent.NotThreadSafe; import java.net.URI; import java.util.HashMap; @@ -52,7 +51,7 @@ public CachedMetaDataStore(RecordMetaDataStore backingStore) { } @Override - public RecordMetaDataProvider loadMetaData(@Nonnull Transaction txn, @Nonnull URI dbUri, @Nonnull String schemaName) throws RelationalException { + public RecordMetaDataProvider loadMetaData(Transaction txn, URI dbUri, String schemaName) throws RelationalException { String key = (dbUri.getPath() + "/" + schemaName).toUpperCase(Locale.ROOT); CacheCell cacheCell = cachedProviders.get(key); if (cacheCell == null) { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/CatalogMetaDataProvider.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/CatalogMetaDataProvider.java index 31ab158ee74..67628483d47 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/CatalogMetaDataProvider.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/CatalogMetaDataProvider.java @@ -33,7 +33,6 @@ import com.apple.foundationdb.relational.recordlayer.metadata.RecordLayerSchemaTemplate; import com.apple.foundationdb.relational.util.Assert; -import javax.annotation.Nonnull; import java.net.URI; @API(API.Status.EXPERIMENTAL) @@ -47,17 +46,16 @@ public class CatalogMetaDataProvider implements RecordMetaDataProvider { private volatile RecordMetaData cachedMetaData; - public CatalogMetaDataProvider(@Nonnull StoreCatalog storeCatalog, - @Nonnull URI dbUri, - @Nonnull String schemaName, - @Nonnull Transaction txn) { + public CatalogMetaDataProvider(StoreCatalog storeCatalog, + URI dbUri, + String schemaName, + Transaction txn) { this.storeCatalog = storeCatalog; this.dbUri = dbUri; this.schemaName = schemaName; this.txn = txn; } - @Nonnull @Override public RecordMetaData getRecordMetaData() { RecordMetaData metaData = cachedMetaData; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/CatalogMetaDataStore.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/CatalogMetaDataStore.java index febc227faef..990394a771e 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/CatalogMetaDataStore.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/CatalogMetaDataStore.java @@ -27,7 +27,6 @@ import com.apple.foundationdb.relational.api.catalog.StoreCatalog; import com.apple.foundationdb.relational.api.exceptions.RelationalException; -import javax.annotation.Nonnull; import java.net.URI; /** @@ -42,7 +41,7 @@ public CatalogMetaDataStore(StoreCatalog storeCatalog) { } @Override - public RecordMetaDataProvider loadMetaData(@Nonnull Transaction txn, @Nonnull URI dbUri, @Nonnull String schemaUrl) throws RelationalException { + public RecordMetaDataProvider loadMetaData(Transaction txn, URI dbUri, String schemaUrl) throws RelationalException { return new CatalogMetaDataProvider(storeCatalog, dbUri, schemaUrl, txn); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalog.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalog.java index c2da5915dcd..832486e7b2c 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalog.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalog.java @@ -72,8 +72,7 @@ import com.google.protobuf.ExtensionRegistry; import com.google.protobuf.Message; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.net.URI; import java.sql.SQLException; import java.util.Locale; @@ -130,7 +129,7 @@ class RecordLayerStoreCatalog implements StoreCatalog, KeySpaceProvider { private final RecordLayerSchema catalogSchema; @SpotBugsSuppressWarnings(value = "CT_CONSTRUCTOR_THROW", justification = "Hard to remove exception with current inheritance") - RecordLayerStoreCatalog(@Nonnull final KeySpace keySpace) throws RelationalException { + RecordLayerStoreCatalog(final KeySpace keySpace) throws RelationalException { this.keySpace = keySpace; this.catalogSchemaPath = RelationalKeyspaceProvider.toDatabasePath(DASH_DASH_SYS, keySpace) .schemaPath(RelationalKeyspaceProvider.CATALOG); @@ -152,7 +151,7 @@ class RecordLayerStoreCatalog implements StoreCatalog, KeySpaceProvider { * @return {@code this} StoreCatalog instance for method chaining * @throws RelationalException if catalog initialization fails */ - StoreCatalog initialize(@Nonnull final Transaction createTxn) throws RelationalException { + StoreCatalog initialize(final Transaction createTxn) throws RelationalException { return initialize(createTxn, new RecordLayerStoreSchemaTemplateCatalog(catalogSchema, catalogSchemaPath)); } @@ -165,7 +164,7 @@ StoreCatalog initialize(@Nonnull final Transaction createTxn) throws RelationalE * @return this StoreCatalog instance for method chaining * @throws RelationalException if catalog initialization fails */ - StoreCatalog initialize(@Nonnull final Transaction createTxn, @Nonnull final SchemaTemplateCatalog schemaTemplateCatalog) + StoreCatalog initialize(final Transaction createTxn, final SchemaTemplateCatalog schemaTemplateCatalog) throws RelationalException { try { // Set Catalog store's state cacheability to be true to make frequent opening of store a light operation. @@ -198,9 +197,8 @@ public SchemaTemplateCatalog getSchemaTemplateCatalog() { return schemaTemplateCatalog; } - @Nonnull @Override - public RecordLayerSchema loadSchema(@Nonnull Transaction txn, @Nonnull URI databaseId, @Nonnull String schemaName) throws RelationalException { + public RecordLayerSchema loadSchema(Transaction txn, URI databaseId, String schemaName) throws RelationalException { var recordStore = RecordLayerStoreUtils.openRecordStore(txn, this.catalogSchemaPath, this.catalogRecordMetaDataProvider); Assert.notNull(recordStore); @@ -212,9 +210,9 @@ public RecordLayerSchema loadSchema(@Nonnull Transaction txn, @Nonnull URI datab } @Nullable - private RecordLayerSchema loadSchemaIfExists(@Nonnull final Transaction txn, @Nonnull final URI databaseId, - @Nonnull final String schemaName, - @Nonnull final FDBRecordStoreBase recordStore) throws RelationalException { + private RecordLayerSchema loadSchemaIfExists(final Transaction txn, final URI databaseId, + final String schemaName, + final FDBRecordStoreBase recordStore) throws RelationalException { final Tuple primaryKey = Tuple.from(SystemTableRegistry.SCHEMA_RECORD_TYPE_KEY, databaseId.getPath(), schemaName); try { final FDBStoredRecord record = recordStore.loadRecord(primaryKey); @@ -229,9 +227,9 @@ private RecordLayerSchema loadSchemaIfExists(@Nonnull final Transaction txn, @No } @Override - public void saveSchema(@Nonnull final Transaction txn, @Nonnull final Schema schema, + public void saveSchema(final Transaction txn, final Schema schema, boolean createDatabaseIfNecessary, - @Nonnull SchemaExistsBehavior existsBehavior) throws RelationalException { + SchemaExistsBehavior existsBehavior) throws RelationalException { var recordStore = RecordLayerStoreUtils.openRecordStore(txn, this.catalogSchemaPath, this.catalogRecordMetaDataProvider); CatalogValidator.validateSchema(schema); @@ -269,7 +267,7 @@ public void saveSchema(@Nonnull final Transaction txn, @Nonnull final Schema sch } @Override - public void repairSchema(@Nonnull Transaction txn, @Nonnull String databaseId, @Nonnull String schemaName) throws RelationalException { + public void repairSchema(Transaction txn, String databaseId, String schemaName) throws RelationalException { // a read-modify-write loop, done in 1 transaction final RecordLayerSchema schema = loadSchema(txn, URI.create(databaseId), schemaName); // load latest schema template @@ -279,7 +277,7 @@ public void repairSchema(@Nonnull Transaction txn, @Nonnull String databaseId, @ } @Override - public void createDatabase(@Nonnull Transaction txn, URI dbUri) throws RelationalException { + public void createDatabase(Transaction txn, URI dbUri) throws RelationalException { var recordStore = RecordLayerStoreUtils.openRecordStore(txn, this.catalogSchemaPath, this.catalogRecordMetaDataProvider); try { @@ -290,7 +288,7 @@ public void createDatabase(@Nonnull Transaction txn, URI dbUri) throws Relationa } @SuppressWarnings("deprecation") // need to replace protobuf data builder - private void createDatabase(@Nonnull FDBRecordStoreBase recordStore, URI dbUri) throws RelationalException { + private void createDatabase(FDBRecordStoreBase recordStore, URI dbUri) throws RelationalException { try { ProtobufDataBuilder pmd = new ProtobufDataBuilder(catalogRecordMetaDataProvider.getRecordMetaData().getRecordType(SystemTableRegistry.DATABASE_TABLE_NAME).getDescriptor()); Message m = pmd.setField("DATABASE_ID", dbUri.getPath()).build(); @@ -302,7 +300,7 @@ private void createDatabase(@Nonnull FDBRecordStoreBase recordStore, UR @SuppressWarnings("PMD.CloseResource") // cursor lifetime extends into lifetime of returned result set @Override - public RelationalResultSet listDatabases(@Nonnull Transaction txn, @Nonnull Continuation continuation) throws RelationalException { + public RelationalResultSet listDatabases(Transaction txn, Continuation continuation) throws RelationalException { var recordStore = RecordLayerStoreUtils.openRecordStore(txn, this.catalogSchemaPath, this.catalogRecordMetaDataProvider); Tuple key = Tuple.from(SystemTableRegistry.DATABASE_INFO_RECORD_TYPE_KEY); @@ -313,7 +311,7 @@ public RelationalResultSet listDatabases(@Nonnull Transaction txn, @Nonnull Cont @SuppressWarnings("PMD.CloseResource") // cursor lifetime extends into lifetime of returned result set @Override - public RelationalResultSet listSchemas(@Nonnull Transaction txn, @Nonnull Continuation continuation) throws RelationalException { + public RelationalResultSet listSchemas(Transaction txn, Continuation continuation) throws RelationalException { var recordStore = RecordLayerStoreUtils.openRecordStore(txn, this.catalogSchemaPath, this.catalogRecordMetaDataProvider); Tuple key = Tuple.from(SystemTableRegistry.SCHEMA_RECORD_TYPE_KEY); @@ -325,7 +323,7 @@ public RelationalResultSet listSchemas(@Nonnull Transaction txn, @Nonnull Contin @SuppressWarnings("PMD.CloseResource") // cursor lifetime extends into lifetime of returned result set @Override - public RelationalResultSet listSchemas(@Nonnull Transaction txn, @Nonnull URI databaseId, @Nonnull Continuation continuation) throws RelationalException { + public RelationalResultSet listSchemas(Transaction txn, URI databaseId, Continuation continuation) throws RelationalException { var recordStore = RecordLayerStoreUtils.openRecordStore(txn, this.catalogSchemaPath, this.catalogRecordMetaDataProvider); Tuple key = Tuple.from(SystemTableRegistry.SCHEMA_RECORD_TYPE_KEY, databaseId.getPath()); @@ -335,7 +333,7 @@ public RelationalResultSet listSchemas(@Nonnull Transaction txn, @Nonnull URI da } @Override - public void deleteSchema(@Nonnull Transaction txn, @Nonnull URI dbUri, @Nonnull String schemaName) throws RelationalException { + public void deleteSchema(Transaction txn, URI dbUri, String schemaName) throws RelationalException { var recordStore = RecordLayerStoreUtils.openRecordStore(txn, this.catalogSchemaPath, this.catalogRecordMetaDataProvider); try { @@ -347,13 +345,13 @@ public void deleteSchema(@Nonnull Transaction txn, @Nonnull URI dbUri, @Nonnull } @Override - public boolean doesDatabaseExist(@Nonnull Transaction txn, @Nonnull URI databaseId) throws RelationalException { + public boolean doesDatabaseExist(Transaction txn, URI databaseId) throws RelationalException { var recordStore = RecordLayerStoreUtils.openRecordStore(txn, this.catalogSchemaPath, this.catalogRecordMetaDataProvider); return doesDatabaseExist(recordStore, databaseId); } - private boolean doesDatabaseExist(@Nonnull FDBRecordStoreBase recordStore, @Nonnull URI databaseId) throws RelationalException { + private boolean doesDatabaseExist(FDBRecordStoreBase recordStore, URI databaseId) throws RelationalException { try { String dbId = databaseId.getPath(); return recordStore.loadRecord(Tuple.from(SystemTableRegistry.DATABASE_INFO_RECORD_TYPE_KEY, dbId)) != null; @@ -363,7 +361,7 @@ private boolean doesDatabaseExist(@Nonnull FDBRecordStoreBase recordSto } @Override - public boolean doesSchemaExist(@Nonnull Transaction txn, @Nonnull URI dbUri, @Nonnull String schemaName) throws RelationalException { + public boolean doesSchemaExist(Transaction txn, URI dbUri, String schemaName) throws RelationalException { var recordStore = RecordLayerStoreUtils.openRecordStore(txn, this.catalogSchemaPath, this.catalogRecordMetaDataProvider); try { @@ -375,7 +373,7 @@ public boolean doesSchemaExist(@Nonnull Transaction txn, @Nonnull URI dbUri, @No } @Override - public boolean deleteDatabase(@Nonnull Transaction txn, @Nonnull URI dbUrl, boolean throwIfDoesNotExist) throws RelationalException { + public boolean deleteDatabase(Transaction txn, URI dbUrl, boolean throwIfDoesNotExist) throws RelationalException { var recordStore = RecordLayerStoreUtils.openRecordStore(txn, this.catalogSchemaPath, this.catalogRecordMetaDataProvider); try { @@ -399,7 +397,6 @@ public boolean deleteDatabase(@Nonnull Transaction txn, @Nonnull URI dbUrl, bool return true; } - @Nonnull @Override public KeySpace getKeySpace() { return keySpace; @@ -408,7 +405,7 @@ public KeySpace getKeySpace() { // delete schemas for the matching dbUri. // returns true if the operation completes, false when the operation cannot complete because of txn timeout // throws exception otherwise. - private boolean deleteSchemas(@Nonnull FDBRecordStoreBase recordStore, @Nonnull URI dbUri) throws RelationalException { + private boolean deleteSchemas(FDBRecordStoreBase recordStore, URI dbUri) throws RelationalException { Tuple key = Tuple.from(SystemTableRegistry.SCHEMA_RECORD_TYPE_KEY, dbUri.getPath()); try (RecordCursor> cursor = recordStore.scanRecords(new TupleRange(key, key, EndpointType.RANGE_INCLUSIVE, @@ -434,10 +431,10 @@ private boolean deleteSchemas(@Nonnull FDBRecordStoreBase recordStore, } @SuppressWarnings("deprecation") // need to replace protobuf data builder - private void putSchema(@Nonnull final RecordLayerSchema schema, @Nonnull final FDBRecordStoreBase recordStore) throws RelationalException { + private void putSchema(final RecordLayerSchema schema, final FDBRecordStoreBase recordStore) throws RelationalException { try { - @Nonnull final ProtobufDataBuilder pmd = new ProtobufDataBuilder(catalogRecordMetaDataProvider.getRecordMetaData().getRecordType(SystemTableRegistry.SCHEMAS_TABLE_NAME).getDescriptor()); - @Nonnull final Message m = pmd.setField("DATABASE_ID", schema.getDatabaseName()) + final ProtobufDataBuilder pmd = new ProtobufDataBuilder(catalogRecordMetaDataProvider.getRecordMetaData().getRecordType(SystemTableRegistry.SCHEMAS_TABLE_NAME).getDescriptor()); + final Message m = pmd.setField("DATABASE_ID", schema.getDatabaseName()) .setField("SCHEMA_NAME", schema.getName()) .setField("TEMPLATE_NAME", schema.getSchemaTemplate().getName()) .setField("TEMPLATE_VERSION", schema.getSchemaTemplate().getVersion()) @@ -452,8 +449,7 @@ private static StructMetaData getMetaData(Descriptors.Descriptor descriptor) thr return RelationalStructMetaData.of((DataType.StructType) DataTypeUtils.toRelationalType(ProtobufDdlUtil.recordFromDescriptor(descriptor))); } - @Nonnull - private Tuple getSchemaKey(@Nonnull URI databaseId, @Nonnull String schemaName) { + private Tuple getSchemaKey(URI databaseId, String schemaName) { return Tuple.from(SystemTableRegistry.SCHEMA_RECORD_TYPE_KEY, databaseId.getPath(), schemaName); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreSchemaTemplateCatalog.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreSchemaTemplateCatalog.java index c755308d7e3..126c083200c 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreSchemaTemplateCatalog.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreSchemaTemplateCatalog.java @@ -65,8 +65,7 @@ import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.Message; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.sql.SQLException; import java.util.Objects; @@ -76,7 +75,6 @@ */ class RecordLayerStoreSchemaTemplateCatalog implements SchemaTemplateCatalog { - @Nonnull private static final com.google.protobuf.ExtensionRegistry registry = com.google.protobuf.ExtensionRegistry.newInstance(); static { @@ -84,13 +82,10 @@ class RecordLayerStoreSchemaTemplateCatalog implements SchemaTemplateCatalog { registry.add(com.apple.foundationdb.record.RecordMetaDataOptionsProto.record); } - @Nonnull private final RecordLayerSchema catalogSchema; - @Nonnull private final RelationalKeyspaceProvider.RelationalSchemaPath catalogSchemaPath; - @Nonnull private final RecordMetaDataProvider catalogRecordMetaDataProvider; /** @@ -102,8 +97,8 @@ class RecordLayerStoreSchemaTemplateCatalog implements SchemaTemplateCatalog { * (this should not occur under normal conditions) */ @SpotBugsSuppressWarnings(value = "CT_CONSTRUCTOR_THROW", justification = "Hard to remove exception with current inheritance") - RecordLayerStoreSchemaTemplateCatalog(@Nonnull final RecordLayerSchema catalogSchema, - @Nonnull final RelationalKeyspaceProvider.RelationalSchemaPath catalogSchemaPath) throws RelationalException { + RecordLayerStoreSchemaTemplateCatalog(final RecordLayerSchema catalogSchema, + final RelationalKeyspaceProvider.RelationalSchemaPath catalogSchemaPath) throws RelationalException { this.catalogSchema = catalogSchema; this.catalogSchemaPath = catalogSchemaPath; this.catalogRecordMetaDataProvider = RecordMetaData.build(this.catalogSchema.getSchemaTemplate() @@ -111,7 +106,7 @@ class RecordLayerStoreSchemaTemplateCatalog implements SchemaTemplateCatalog { } @Override - public boolean doesSchemaTemplateExist(@Nonnull Transaction txn, @Nonnull String schemaTemplateName) + public boolean doesSchemaTemplateExist(Transaction txn, String schemaTemplateName) throws RelationalException { Tuple key = getSchemaTemplatePrimaryKey(schemaTemplateName); var recordStore = RecordLayerStoreUtils.openRecordStore(txn, this.catalogSchemaPath, @@ -130,7 +125,7 @@ public boolean doesSchemaTemplateExist(@Nonnull Transaction txn, @Nonnull String } @Override - public boolean doesSchemaTemplateExist(@Nonnull Transaction txn, @Nonnull String schemaTemplateName, int version) + public boolean doesSchemaTemplateExist(Transaction txn, String schemaTemplateName, int version) throws RelationalException { if (schemaTemplateName.equals(this.catalogSchema.getSchemaTemplate().getName()) && version == this.catalogSchema.getSchemaTemplate().getVersion()) { @@ -172,9 +167,8 @@ private static Tuple getSchemaTemplatePrimaryKey(String schemaTemplateName) { return Tuple.from(SystemTableRegistry.SCHEMA_TEMPLATE_RECORD_TYPE_KEY, schemaTemplateName); } - @Nonnull @Override - public SchemaTemplate loadSchemaTemplate(@Nonnull final Transaction txn, @Nonnull final String templateName) + public SchemaTemplate loadSchemaTemplate(final Transaction txn, final String templateName) throws RelationalException { final var key = getSchemaTemplatePrimaryKey(templateName); final var recordStore = RecordLayerStoreUtils.openRecordStore(txn, catalogSchemaPath, catalogRecordMetaDataProvider); @@ -190,9 +184,8 @@ public SchemaTemplate loadSchemaTemplate(@Nonnull final Transaction txn, @Nonnul } } - @Nonnull @Override - public SchemaTemplate loadSchemaTemplate(@Nonnull final Transaction txn, @Nonnull final String templateName, int version) + public SchemaTemplate loadSchemaTemplate(final Transaction txn, final String templateName, int version) throws RelationalException { try { // TODO: I seem to be doing way more work than I should have to. Someone please set me right. Stack 05/2023. @@ -212,8 +205,7 @@ public SchemaTemplate loadSchemaTemplate(@Nonnull final Transaction txn, @Nonnul /** * Instantiate an instance of {@link SchemaTemplate} using content of the passed {@link Message}. */ - @Nonnull - private static SchemaTemplate toSchemaTemplate(@Nonnull final Message message) throws InvalidProtocolBufferException { + private static SchemaTemplate toSchemaTemplate(final Message message) throws InvalidProtocolBufferException { // we should probably memoize a Message -> RecordLayerSchemaTemplate relation to avoid repetitive // deserialization of the same message over and over again. final Descriptors.Descriptor descriptor = message.getDescriptorForType(); @@ -226,7 +218,7 @@ private static SchemaTemplate toSchemaTemplate(@Nonnull final Message message) t @Override @SuppressWarnings("deprecation") // need to replace protobuf data builder - public void createTemplate(@Nonnull Transaction txn, @Nonnull SchemaTemplate newTemplate) throws RelationalException { + public void createTemplate(Transaction txn, SchemaTemplate newTemplate) throws RelationalException { var recordStore = RecordLayerStoreUtils.openRecordStore(txn, this.catalogSchemaPath, this.catalogRecordMetaDataProvider); Assert.notNull(recordStore); @@ -248,7 +240,7 @@ public void createTemplate(@Nonnull Transaction txn, @Nonnull SchemaTemplate new @SuppressWarnings("PMD.CloseResource") // lifetime of cursor extends into lifetime of returned result set @Override - public RelationalResultSet listTemplates(@Nonnull Transaction txn) { + public RelationalResultSet listTemplates(Transaction txn) { Tuple key = Tuple.from(SystemTableRegistry.SCHEMA_TEMPLATE_RECORD_TYPE_KEY); try { var recordStore = RecordLayerStoreUtils.openRecordStore(txn, this.catalogSchemaPath, @@ -283,7 +275,7 @@ private Row transformSchemaTemplates(@Nullable FDBStoredRecord record) } @Override - public void deleteTemplate(@Nonnull Transaction txn, @Nonnull String templateName, boolean throwIfDoesNotExist) throws RelationalException { + public void deleteTemplate(Transaction txn, String templateName, boolean throwIfDoesNotExist) throws RelationalException { Tuple key = getSchemaTemplatePrimaryKey(templateName); try { var recordStore = RecordLayerStoreUtils.openRecordStore(txn, this.catalogSchemaPath, @@ -315,7 +307,7 @@ public void deleteTemplate(@Nonnull Transaction txn, @Nonnull String templateNam } @Override - public void deleteTemplate(@Nonnull Transaction txn, @Nonnull String templateName, int version, boolean throwIfDoesNotExist) + public void deleteTemplate(Transaction txn, String templateName, int version, boolean throwIfDoesNotExist) throws RelationalException { var recordStore = RecordLayerStoreUtils.openRecordStore(txn, this.catalogSchemaPath, this.catalogRecordMetaDataProvider); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreUtils.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreUtils.java index 2f1e2d6aeee..fc8b52a3eaf 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreUtils.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreUtils.java @@ -32,7 +32,6 @@ import com.google.protobuf.Message; -import javax.annotation.Nonnull; /** * Functionality shared by classes in this package accessing RecordLayer. @@ -46,7 +45,7 @@ class RecordLayerStoreUtils { * @return Open RecordStore over passed context. * @throws RelationalException Thrown if problem opening RecordStore. */ - static FDBRecordStoreBase openRecordStore(@Nonnull Transaction txn, + static FDBRecordStoreBase openRecordStore(Transaction txn, RelationalKeyspaceProvider.RelationalSchemaPath schemaPath, RecordMetaDataProvider metaDataProvider) throws RelationalException { try { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordMetaDataStore.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordMetaDataStore.java index 72b817b6dba..43800963a65 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordMetaDataStore.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordMetaDataStore.java @@ -24,7 +24,6 @@ import com.apple.foundationdb.relational.api.Transaction; import com.apple.foundationdb.relational.api.exceptions.RelationalException; -import javax.annotation.Nonnull; import java.net.URI; public interface RecordMetaDataStore { @@ -37,5 +36,5 @@ public interface RecordMetaDataStore { * @return the metadata for the schema. * @throws RelationalException if the metadata cannot be loaded. */ - RecordMetaDataProvider loadMetaData(@Nonnull Transaction txn, @Nonnull URI dbUri, @Nonnull String schemaName) throws RelationalException; + RecordMetaDataProvider loadMetaData(Transaction txn, URI dbUri, String schemaName) throws RelationalException; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/StoreCatalogProvider.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/StoreCatalogProvider.java index f94b88e1b81..c00202cf221 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/StoreCatalogProvider.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/StoreCatalogProvider.java @@ -30,7 +30,6 @@ import com.apple.foundationdb.relational.api.exceptions.RelationalException; import com.apple.foundationdb.relational.recordlayer.RelationalKeyspaceProvider; -import javax.annotation.Nonnull; /** * {@link StoreCatalog} supplier. @@ -51,7 +50,7 @@ public class StoreCatalogProvider { * @return a fully initialized {@link StoreCatalog} instance * @throws RelationalException if catalog creation or initialization fails */ - public static StoreCatalog getCatalog(@Nonnull final Transaction txn, @Nonnull final KeySpace keySpace) throws RelationalException { + public static StoreCatalog getCatalog(final Transaction txn, final KeySpace keySpace) throws RelationalException { return new RecordLayerStoreCatalog(keySpace).initialize(txn); } @@ -62,7 +61,7 @@ public static StoreCatalog getCatalogWithNoTemplateOperations(Transaction txn) t // Do not allow repairing Schema operation because they cannot work with NoOpSchemaTemplateCatalog. final var storeCatalog = new RecordLayerStoreCatalog(RelationalKeyspaceProvider.instance().getKeySpace()) { @Override - public void repairSchema(@Nonnull Transaction txn, @Nonnull String databaseId, @Nonnull String schemaName) + public void repairSchema(Transaction txn, String databaseId, String schemaName) throws RelationalException { throw new OperationUnsupportedException("This store catalog does not support repairing schema."); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/TransactionBoundDatabase.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/TransactionBoundDatabase.java index ac151793636..bdedad448c4 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/TransactionBoundDatabase.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/TransactionBoundDatabase.java @@ -46,8 +46,7 @@ import com.apple.foundationdb.relational.recordlayer.storage.BackingStore; import com.apple.foundationdb.relational.transactionbound.catalog.HollowStoreCatalog; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.net.URI; /** @@ -69,21 +68,19 @@ public class TransactionBoundDatabase extends AbstractDatabase { URI uri; private static final MetadataOperationsFactory onlyTemporaryFunctionOperationsFactory = new AbstractMetadataOperationsFactory() { - @Nonnull @Override - public ConstantAction getCreateTemporaryFunctionConstantAction(@Nonnull final SchemaTemplate template, final boolean throwIfExists, - @Nonnull final RecordLayerInvokedRoutine invokedRoutine) { + public ConstantAction getCreateTemporaryFunctionConstantAction(final SchemaTemplate template, final boolean throwIfExists, + final RecordLayerInvokedRoutine invokedRoutine) { return new CreateTemporaryFunctionConstantAction(template, throwIfExists, invokedRoutine); } - @Nonnull @Override - public ConstantAction getDropTemporaryFunctionConstantAction(final boolean throwIfNotExists, @Nonnull final String temporaryFunctionName) { + public ConstantAction getDropTemporaryFunctionConstantAction(final boolean throwIfNotExists, final String temporaryFunctionName) { return new DropTemporaryFunctionConstantAction(throwIfNotExists, temporaryFunctionName); } }; - public TransactionBoundDatabase(@Nonnull URI uri, @Nonnull Options options, @Nullable RelationalPlanCache planCache, + public TransactionBoundDatabase(URI uri, Options options, @Nullable RelationalPlanCache planCache, @Nullable KeySpace keySpace) { super(onlyTemporaryFunctionOperationsFactory, NoOpQueryFactory.INSTANCE, planCache, options); this.uri = uri; @@ -105,7 +102,7 @@ public RelationalConnection connect(@Nullable Transaction transaction) throws Re } @Override - public BackingStore loadRecordStore(@Nonnull String schemaId, @Nonnull FDBRecordStoreBase.StoreExistenceCheck existenceCheck) { + public BackingStore loadRecordStore(String schemaId, FDBRecordStoreBase.StoreExistenceCheck existenceCheck) { return store; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/package-info.java index 37f6e1ea626..090e9b8356e 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/package-info.java @@ -22,4 +22,7 @@ * A RecordLayer-based implementation of the catalog. */ +@NullMarked package com.apple.foundationdb.relational.recordlayer.catalog; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/DatabaseInfoSystemTable.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/DatabaseInfoSystemTable.java index c418bf46af4..6db3368e095 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/DatabaseInfoSystemTable.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/DatabaseInfoSystemTable.java @@ -32,7 +32,6 @@ import com.apple.foundationdb.relational.recordlayer.metadata.RecordLayerSchemaTemplate; import com.apple.foundationdb.relational.recordlayer.metadata.RecordLayerTable; -import javax.annotation.Nonnull; import java.util.List; /** @@ -50,14 +49,13 @@ public class DatabaseInfoSystemTable implements SystemTable { .setKeyExpression(new GroupingKeyExpression(Key.Expressions.empty(), 0)) .build(); - @Nonnull @Override public String getName() { return TABLE_NAME; } @Override - public void addDefinition(@Nonnull final RecordLayerSchemaTemplate.Builder typingContext) { + public void addDefinition(final RecordLayerSchemaTemplate.Builder typingContext) { typingContext.addTable(getType()); } @@ -72,7 +70,6 @@ public RecordLayerTable getType() { .build(); } - @Nonnull @Override public KeyExpression getPrimaryKeyDefinition() { return Key.Expressions.concat(Key.Expressions.recordType(), Key.Expressions.field(DATABASE_ID)); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/SchemaSystemTable.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/SchemaSystemTable.java index fae4a44190b..4d562874ba4 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/SchemaSystemTable.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/SchemaSystemTable.java @@ -32,7 +32,6 @@ import com.apple.foundationdb.relational.recordlayer.metadata.RecordLayerSchemaTemplate; import com.apple.foundationdb.relational.recordlayer.metadata.RecordLayerTable; -import javax.annotation.Nonnull; import java.util.List; import static com.apple.foundationdb.record.metadata.Key.Expressions.concat; @@ -62,14 +61,13 @@ public class SchemaSystemTable implements SystemTable { .setKeyExpression(concat(field(TEMPLATE_NAME), field(TEMPLATE_VERSION), field(DATABASE_ID), field(SCHEMA_NAME))) .build(); - @Nonnull @Override public String getName() { return TABLE_NAME; } @Override - public void addDefinition(@Nonnull final RecordLayerSchemaTemplate.Builder schemaBuilder) { + public void addDefinition(final RecordLayerSchemaTemplate.Builder schemaBuilder) { // construct the table type. schemaBuilder.addTable(getType()); } @@ -90,7 +88,6 @@ public RecordLayerTable getType() { .build(); } - @Nonnull @Override public KeyExpression getPrimaryKeyDefinition() { return concat(Key.Expressions.recordType(), Key.Expressions.concatenateFields(DATABASE_ID, SCHEMA_NAME)); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/SchemaTemplateSystemTable.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/SchemaTemplateSystemTable.java index 63d76ae0286..c4358e86eba 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/SchemaTemplateSystemTable.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/SchemaTemplateSystemTable.java @@ -29,7 +29,6 @@ import com.apple.foundationdb.relational.recordlayer.metadata.RecordLayerSchemaTemplate; import com.apple.foundationdb.relational.recordlayer.metadata.RecordLayerTable; -import javax.annotation.Nonnull; import java.util.List; @API(API.Status.EXPERIMENTAL) @@ -43,14 +42,13 @@ public class SchemaTemplateSystemTable implements SystemTable { */ public static final String METADATA = "META_DATA"; - @Nonnull @Override public String getName() { return TABLE_NAME; } @Override - public void addDefinition(@Nonnull final RecordLayerSchemaTemplate.Builder schemaBuilder) { + public void addDefinition(final RecordLayerSchemaTemplate.Builder schemaBuilder) { // construct the table type. schemaBuilder.addTable(getType()); } @@ -68,7 +66,6 @@ public RecordLayerTable getType() { .build(); } - @Nonnull @Override public KeyExpression getPrimaryKeyDefinition() { return Key.Expressions.concat(Key.Expressions.recordType(), Key.Expressions.concatenateFields(TEMPLATE_NAME, TEMPLATE_VERSION)); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/SystemTable.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/SystemTable.java index abe9582efde..37e23b009ec 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/SystemTable.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/SystemTable.java @@ -24,7 +24,6 @@ import com.apple.foundationdb.relational.recordlayer.metadata.RecordLayerSchemaTemplate; import com.apple.foundationdb.relational.recordlayer.metadata.RecordLayerTable; -import javax.annotation.Nonnull; /** * This interface provides an abstraction for a database system table (view). @@ -49,7 +48,6 @@ public interface SystemTable { * Returns the name of the system table. * @return The name of the system table. */ - @Nonnull String getName(); /** @@ -63,7 +61,7 @@ public interface SystemTable { * * @param schemaBuilder The current schema builder used to populate schema template information. */ - void addDefinition(@Nonnull RecordLayerSchemaTemplate.Builder schemaBuilder); + void addDefinition(RecordLayerSchemaTemplate.Builder schemaBuilder); RecordLayerTable getType(); @@ -71,7 +69,6 @@ public interface SystemTable { * Returns the primary key definition of the system table. Each system table must have a primary key. * @return The primary key. */ - @Nonnull KeyExpression getPrimaryKeyDefinition(); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/SystemTableRegistry.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/SystemTableRegistry.java index 6b7e3946b90..772f51a8e2c 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/SystemTableRegistry.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/SystemTableRegistry.java @@ -22,7 +22,6 @@ import com.apple.foundationdb.annotation.API; -import javax.annotation.Nonnull; import java.util.Map; /** @@ -42,14 +41,12 @@ public final class SystemTableRegistry { public static final String DATABASE_TABLE_NAME = "DATABASES"; public static final String SCHEMA_TEMPLATE_TABLE_NAME = "TEMPLATES"; - @Nonnull private static final Map tablesMap = Map.of( SCHEMAS_TABLE_NAME, new SchemaSystemTable(), DATABASE_TABLE_NAME, new DatabaseInfoSystemTable(), SCHEMA_TEMPLATE_TABLE_NAME, new SchemaTemplateSystemTable() ); - @Nonnull public static SystemTable getSystemTable(String key) { final SystemTable systemTable = tablesMap.get(key); if (systemTable == null) { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/package-info.java index 303e7a9b2bc..4b6b41dccd7 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/systables/package-info.java @@ -22,4 +22,7 @@ * This package is aimed to hold all the structures needed to represent system tables and system views in Relational. */ +@NullMarked package com.apple.foundationdb.relational.recordlayer.catalog.systables; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/AbstractMetadataOperationsFactory.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/AbstractMetadataOperationsFactory.java index aad538d9d73..dc94936a82a 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/AbstractMetadataOperationsFactory.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/AbstractMetadataOperationsFactory.java @@ -26,60 +26,51 @@ import com.apple.foundationdb.relational.api.metadata.SchemaTemplate; import com.apple.foundationdb.relational.recordlayer.metadata.RecordLayerInvokedRoutine; -import javax.annotation.Nonnull; import java.net.URI; /** * Skeleton implementation of a ConstantActionFactory. */ public abstract class AbstractMetadataOperationsFactory implements MetadataOperationsFactory { - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, Options templateProperties) { return NoOpMetadataOperationsFactory.INSTANCE.getSaveSchemaTemplateConstantAction(template, templateProperties); } - @Nonnull @Override - public ConstantAction getCreateDatabaseConstantAction(@Nonnull URI dbPath, @Nonnull Options constantActionOptions) { + public ConstantAction getCreateDatabaseConstantAction(URI dbPath, Options constantActionOptions) { return NoOpMetadataOperationsFactory.INSTANCE.getCreateDatabaseConstantAction(dbPath, constantActionOptions); } - @Nonnull @Override - public ConstantAction getCreateSchemaConstantAction(@Nonnull URI dbUri, @Nonnull String schemaName, @Nonnull String templateId, Options constantActionOptions) { + public ConstantAction getCreateSchemaConstantAction(URI dbUri, String schemaName, String templateId, Options constantActionOptions) { return NoOpMetadataOperationsFactory.INSTANCE.getCreateSchemaConstantAction(dbUri, schemaName, templateId, constantActionOptions); } - @Nonnull @Override - public ConstantAction getDropDatabaseConstantAction(@Nonnull URI dbUrl, boolean throwIfDoesNotExist, @Nonnull Options options) { + public ConstantAction getDropDatabaseConstantAction(URI dbUrl, boolean throwIfDoesNotExist, Options options) { return NoOpMetadataOperationsFactory.INSTANCE.getDropDatabaseConstantAction(dbUrl, throwIfDoesNotExist, options); } - @Nonnull @Override - public ConstantAction getDropSchemaConstantAction(@Nonnull URI dbPath, @Nonnull String schema, @Nonnull Options options) { + public ConstantAction getDropSchemaConstantAction(URI dbPath, String schema, Options options) { return NoOpMetadataOperationsFactory.INSTANCE.getDropSchemaConstantAction(dbPath, schema, options); } - @Nonnull @Override - public ConstantAction getDropSchemaTemplateConstantAction(@Nonnull String templateId, boolean throwIfDoesNotExist, @Nonnull Options options) { + public ConstantAction getDropSchemaTemplateConstantAction(String templateId, boolean throwIfDoesNotExist, Options options) { return NoOpMetadataOperationsFactory.INSTANCE.getDropSchemaTemplateConstantAction(templateId, throwIfDoesNotExist, options); } - @Nonnull @Override - public ConstantAction getCreateTemporaryFunctionConstantAction(@Nonnull final SchemaTemplate template, boolean throwIfExists, - @Nonnull final RecordLayerInvokedRoutine invokedRoutine) { + public ConstantAction getCreateTemporaryFunctionConstantAction(final SchemaTemplate template, boolean throwIfExists, + final RecordLayerInvokedRoutine invokedRoutine) { return NoOpMetadataOperationsFactory.INSTANCE.getCreateTemporaryFunctionConstantAction(template, throwIfExists, invokedRoutine); } - @Nonnull @Override public ConstantAction getDropTemporaryFunctionConstantAction(boolean throwIfNotExists, - @Nonnull final String temporaryFunctionName) { + final String temporaryFunctionName) { return NoOpMetadataOperationsFactory.INSTANCE.getDropTemporaryFunctionConstantAction(throwIfNotExists, temporaryFunctionName); } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/CreateDatabaseConstantAction.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/CreateDatabaseConstantAction.java index 409b07d19a5..3f984e75668 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/CreateDatabaseConstantAction.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/CreateDatabaseConstantAction.java @@ -30,7 +30,6 @@ import com.apple.foundationdb.relational.api.exceptions.RelationalException; import com.apple.foundationdb.relational.recordlayer.RelationalKeyspaceProvider; -import javax.annotation.Nonnull; import java.net.URI; @API(API.Status.EXPERIMENTAL) @@ -40,9 +39,9 @@ public class CreateDatabaseConstantAction implements ConstantAction { private final StoreCatalog storeCatalog; private final KeySpace keySpace; - public CreateDatabaseConstantAction(@Nonnull URI dbUrl, - @Nonnull StoreCatalog storeCatalog, - @Nonnull KeySpace keySpace) { + public CreateDatabaseConstantAction(URI dbUrl, + StoreCatalog storeCatalog, + KeySpace keySpace) { this.dbUrl = dbUrl; this.storeCatalog = storeCatalog; this.keySpace = keySpace; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/CreateTemporaryFunctionConstantAction.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/CreateTemporaryFunctionConstantAction.java index 02a5ade93ac..af6be1e94a2 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/CreateTemporaryFunctionConstantAction.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/CreateTemporaryFunctionConstantAction.java @@ -29,28 +29,25 @@ import com.apple.foundationdb.relational.recordlayer.metadata.RecordLayerSchemaTemplate; import com.apple.foundationdb.relational.util.Assert; -import javax.annotation.Nonnull; public class CreateTemporaryFunctionConstantAction implements ConstantAction { - @Nonnull private final RecordLayerInvokedRoutine invokedRoutine; private final boolean throwIfExists; - @Nonnull private final SchemaTemplate template; - public CreateTemporaryFunctionConstantAction(@Nonnull final SchemaTemplate template, + public CreateTemporaryFunctionConstantAction(final SchemaTemplate template, boolean throwIfExists, - @Nonnull final RecordLayerInvokedRoutine invokedRoutine) { + final RecordLayerInvokedRoutine invokedRoutine) { this.template = template; this.throwIfExists = throwIfExists; this.invokedRoutine = invokedRoutine; } @Override - public void execute(@Nonnull final Transaction txn) throws RelationalException { + public void execute(final Transaction txn) throws RelationalException { final var transactionBoundSchemaTemplate = Assert.castUnchecked(txn.getBoundSchemaTemplateMaybe().orElse(template), RecordLayerSchemaTemplate.class); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/DropTemporaryFunctionConstantAction.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/DropTemporaryFunctionConstantAction.java index 3425619d391..9bb63d9ca19 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/DropTemporaryFunctionConstantAction.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/DropTemporaryFunctionConstantAction.java @@ -27,17 +27,15 @@ import com.apple.foundationdb.relational.recordlayer.metadata.RecordLayerSchemaTemplate; import com.apple.foundationdb.relational.util.Assert; -import javax.annotation.Nonnull; public class DropTemporaryFunctionConstantAction implements ConstantAction { private final boolean throwIfNotExists; - @Nonnull private final String temporaryFunctionName; public DropTemporaryFunctionConstantAction(boolean throwIfNotExists, - @Nonnull final String temporaryFunctionName) { + final String temporaryFunctionName) { this.throwIfNotExists = throwIfNotExists; this.temporaryFunctionName = temporaryFunctionName; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/NoOpMetadataOperationsFactory.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/NoOpMetadataOperationsFactory.java index 76a371351c6..4333f3b5ee7 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/NoOpMetadataOperationsFactory.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/NoOpMetadataOperationsFactory.java @@ -29,7 +29,6 @@ import com.apple.foundationdb.relational.api.metadata.SchemaTemplate; import com.apple.foundationdb.relational.recordlayer.metadata.RecordLayerInvokedRoutine; -import javax.annotation.Nonnull; import java.net.URI; @API(API.Status.EXPERIMENTAL) @@ -39,53 +38,45 @@ public final class NoOpMetadataOperationsFactory implements MetadataOperationsFa private NoOpMetadataOperationsFactory() { } - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate templateName, @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate templateName, Options templateProperties) { return NoOpConstantAction.INSTANCE; } - @Nonnull @Override - public ConstantAction getCreateDatabaseConstantAction(@Nonnull URI dbPath, @Nonnull Options constantActionOptions) { + public ConstantAction getCreateDatabaseConstantAction(URI dbPath, Options constantActionOptions) { return NoOpConstantAction.INSTANCE; } - @Nonnull @Override - public ConstantAction getCreateSchemaConstantAction(@Nonnull URI dbUri, @Nonnull String schemaName, @Nonnull String templateId, Options constantActionOptions) { + public ConstantAction getCreateSchemaConstantAction(URI dbUri, String schemaName, String templateId, Options constantActionOptions) { return NoOpConstantAction.INSTANCE; } - @Nonnull @Override - public ConstantAction getDropDatabaseConstantAction(@Nonnull URI dbUrl, boolean throwIfDoesNotExist, @Nonnull Options options) { + public ConstantAction getDropDatabaseConstantAction(URI dbUrl, boolean throwIfDoesNotExist, Options options) { return NoOpConstantAction.INSTANCE; } - @Nonnull @Override - public ConstantAction getDropSchemaConstantAction(@Nonnull URI dbPath, @Nonnull String schemaName, @Nonnull Options options) { + public ConstantAction getDropSchemaConstantAction(URI dbPath, String schemaName, Options options) { return NoOpConstantAction.INSTANCE; } - @Nonnull @Override - public ConstantAction getCreateTemporaryFunctionConstantAction(@Nonnull final SchemaTemplate template, boolean throwIfExists, - @Nonnull final RecordLayerInvokedRoutine invokedRoutine) { + public ConstantAction getCreateTemporaryFunctionConstantAction(final SchemaTemplate template, boolean throwIfExists, + final RecordLayerInvokedRoutine invokedRoutine) { return NoOpConstantAction.INSTANCE; } - @Nonnull @Override public ConstantAction getDropTemporaryFunctionConstantAction(boolean throwIfNotExists, - @Nonnull final String temporaryFunctionName) { + final String temporaryFunctionName) { return NoOpConstantAction.INSTANCE; } - @Nonnull @Override - public ConstantAction getDropSchemaTemplateConstantAction(@Nonnull String templateId, boolean throwIfDoesNotExist, @Nonnull Options options) { + public ConstantAction getDropSchemaTemplateConstantAction(String templateId, boolean throwIfDoesNotExist, Options options) { return NoOpConstantAction.INSTANCE; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/RecordLayerCatalogQueryFactory.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/RecordLayerCatalogQueryFactory.java index 96c47c1f0ed..c4998590dc5 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/RecordLayerCatalogQueryFactory.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/RecordLayerCatalogQueryFactory.java @@ -38,7 +38,6 @@ import com.apple.foundationdb.relational.recordlayer.ArrayRow; import com.apple.foundationdb.relational.recordlayer.IteratorResultSet; -import javax.annotation.Nonnull; import java.net.URI; import java.util.ArrayList; import java.util.Collections; @@ -52,9 +51,8 @@ public RecordLayerCatalogQueryFactory(StoreCatalog catalog) { } @Override - public DdlQuery getDescribeSchemaQueryAction(@Nonnull URI dbId, @Nonnull String schemaId) { + public DdlQuery getDescribeSchemaQueryAction(URI dbId, String schemaId) { return new DdlQuery() { - @Nonnull @Override public Type getResultSetMetadata() { return DdlQuery.constructTypeFrom(List.of("DATABASE_PATH", "SCHEMA_NAME", "TABLES", "INDEXES")); @@ -87,9 +85,8 @@ public RelationalResultSet executeAction(Transaction txn) throws RelationalExcep } @Override - public DdlQuery getDescribeSchemaTemplateQueryAction(@Nonnull String schemaId) { + public DdlQuery getDescribeSchemaTemplateQueryAction(String schemaId) { return new DdlQuery() { - @Nonnull @Override public Type getResultSetMetadata() { return DdlQuery.constructTypeFrom(List.of("TEMPLATE_NAME", "TABLES")); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/RecordLayerMetadataOperationsFactory.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/RecordLayerMetadataOperationsFactory.java index 561bf72e984..fbabef14db7 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/RecordLayerMetadataOperationsFactory.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/RecordLayerMetadataOperationsFactory.java @@ -31,7 +31,6 @@ import com.apple.foundationdb.relational.recordlayer.RecordLayerConfig; import com.apple.foundationdb.relational.recordlayer.metadata.RecordLayerInvokedRoutine; -import javax.annotation.Nonnull; import java.net.URI; @API(API.Status.EXPERIMENTAL) @@ -46,61 +45,52 @@ public RecordLayerMetadataOperationsFactory(RecordLayerConfig rlConfig, StoreCat this.baseKeySpace = baseKeySpace; } - @Nonnull @Override - public ConstantAction getDropSchemaTemplateConstantAction(@Nonnull String templateId, boolean throwIfDoesNotExist, @Nonnull Options options) { + public ConstantAction getDropSchemaTemplateConstantAction(String templateId, boolean throwIfDoesNotExist, Options options) { return txn -> { catalog.getSchemaTemplateCatalog().deleteTemplate(txn, templateId, throwIfDoesNotExist); }; } - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, Options templateProperties) { return new SaveSchemaTemplateConstantAction(template, catalog.getSchemaTemplateCatalog()); } - @Nonnull @Override - public ConstantAction getCreateDatabaseConstantAction(@Nonnull URI dbPath, @Nonnull Options constantActionOptions) { + public ConstantAction getCreateDatabaseConstantAction(URI dbPath, Options constantActionOptions) { return new CreateDatabaseConstantAction(dbPath, catalog, baseKeySpace); } - @Nonnull @Override - public ConstantAction getCreateSchemaConstantAction(@Nonnull URI dbUri, @Nonnull String schemaName, @Nonnull String templateId, Options constantActionOptions) { + public ConstantAction getCreateSchemaConstantAction(URI dbUri, String schemaName, String templateId, Options constantActionOptions) { return new RecordLayerCreateSchemaConstantAction(dbUri, schemaName, templateId, rlConfig, baseKeySpace, catalog); } - @Nonnull @Override - public ConstantAction getDropDatabaseConstantAction(@Nonnull URI dbUrl, boolean throwIfDoesNotExist, @Nonnull Options options) { + public ConstantAction getDropDatabaseConstantAction(URI dbUrl, boolean throwIfDoesNotExist, Options options) { return new DropDatabaseConstantAction(dbUrl, throwIfDoesNotExist, catalog, this, options); } - @Nonnull @Override - public ConstantAction getDropSchemaConstantAction(@Nonnull URI dbPath, @Nonnull String schema, @Nonnull Options options) { + public ConstantAction getDropSchemaConstantAction(URI dbPath, String schema, Options options) { return new DropSchemaConstantAction(dbPath, schema, baseKeySpace, catalog); } - @Nonnull - public ConstantAction getSetStoreStateConstantAction(@Nonnull URI dbUri, @Nonnull String schemaName) { + public ConstantAction getSetStoreStateConstantAction(URI dbUri, String schemaName) { return new RecordLayerSetStoreStateConstantAction(dbUri, schemaName, rlConfig, baseKeySpace, catalog); } - @Nonnull @Override - public ConstantAction getCreateTemporaryFunctionConstantAction(@Nonnull SchemaTemplate template, + public ConstantAction getCreateTemporaryFunctionConstantAction(SchemaTemplate template, boolean throwIfExists, - @Nonnull RecordLayerInvokedRoutine invokedRoutine) { + RecordLayerInvokedRoutine invokedRoutine) { return new CreateTemporaryFunctionConstantAction(template, throwIfExists, invokedRoutine); } - @Nonnull @Override public ConstantAction getDropTemporaryFunctionConstantAction(boolean throwIfNotExists, - @Nonnull final String temporaryFunctionName) { + final String temporaryFunctionName) { return new DropTemporaryFunctionConstantAction(throwIfNotExists, temporaryFunctionName); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/ThrowingMetadataOperationsFactory.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/ThrowingMetadataOperationsFactory.java index 2d3145d93ed..79655d821b0 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/ThrowingMetadataOperationsFactory.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/ThrowingMetadataOperationsFactory.java @@ -29,7 +29,6 @@ import com.apple.foundationdb.relational.api.metadata.SchemaTemplate; import com.apple.foundationdb.relational.recordlayer.metadata.RecordLayerInvokedRoutine; -import javax.annotation.Nonnull; import java.net.URI; /** @@ -45,57 +44,49 @@ public final class ThrowingMetadataOperationsFactory implements MetadataOperatio private ThrowingMetadataOperationsFactory() { } - private static RuntimeException reject(@Nonnull final String operation) { + private static RuntimeException reject(final String operation) { return new RelationalException( "DDL operation '" + operation + "' is not allowed in this context", ErrorCode.UNSUPPORTED_OPERATION).toUncheckedWrappedException(); } - @Nonnull @Override - public ConstantAction getSaveSchemaTemplateConstantAction(@Nonnull SchemaTemplate template, @Nonnull Options templateProperties) { + public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate template, Options templateProperties) { throw reject("CREATE SCHEMA TEMPLATE"); } - @Nonnull @Override - public ConstantAction getDropSchemaTemplateConstantAction(@Nonnull String templateId, boolean throwIfDoesNotExist, @Nonnull Options options) { + public ConstantAction getDropSchemaTemplateConstantAction(String templateId, boolean throwIfDoesNotExist, Options options) { throw reject("DROP SCHEMA TEMPLATE"); } - @Nonnull @Override - public ConstantAction getCreateDatabaseConstantAction(@Nonnull URI dbPath, @Nonnull Options constantActionOptions) { + public ConstantAction getCreateDatabaseConstantAction(URI dbPath, Options constantActionOptions) { throw reject("CREATE DATABASE"); } - @Nonnull @Override - public ConstantAction getCreateSchemaConstantAction(@Nonnull URI dbUri, @Nonnull String schemaName, @Nonnull String templateId, Options constantActionOptions) { + public ConstantAction getCreateSchemaConstantAction(URI dbUri, String schemaName, String templateId, Options constantActionOptions) { throw reject("CREATE SCHEMA"); } - @Nonnull @Override - public ConstantAction getDropDatabaseConstantAction(@Nonnull URI dbUrl, boolean throwIfDoesNotExist, @Nonnull Options options) { + public ConstantAction getDropDatabaseConstantAction(URI dbUrl, boolean throwIfDoesNotExist, Options options) { throw reject("DROP DATABASE"); } - @Nonnull @Override - public ConstantAction getDropSchemaConstantAction(@Nonnull URI dbPath, @Nonnull String schemaName, @Nonnull Options options) { + public ConstantAction getDropSchemaConstantAction(URI dbPath, String schemaName, Options options) { throw reject("DROP SCHEMA"); } - @Nonnull @Override - public ConstantAction getCreateTemporaryFunctionConstantAction(@Nonnull SchemaTemplate template, boolean throwIfExists, @Nonnull RecordLayerInvokedRoutine invokedRoutine) { + public ConstantAction getCreateTemporaryFunctionConstantAction(SchemaTemplate template, boolean throwIfExists, RecordLayerInvokedRoutine invokedRoutine) { throw reject("CREATE TEMPORARY FUNCTION"); } - @Nonnull @Override - public ConstantAction getDropTemporaryFunctionConstantAction(boolean throwIfNotExists, @Nonnull String temporaryFunctionName) { + public ConstantAction getDropTemporaryFunctionConstantAction(boolean throwIfNotExists, String temporaryFunctionName) { throw reject("DROP TEMPORARY FUNCTION"); } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/package-info.java index b54eb9cb033..9b3b3e7493b 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/package-info.java @@ -22,4 +22,7 @@ * A RecordLayer-based implementation of DDL logic such as creating and dropping a schema. */ +@NullMarked package com.apple.foundationdb.relational.recordlayer.ddl; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/DataTypeUtils.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/DataTypeUtils.java index 12f98a892a1..cbcad28b4b1 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/DataTypeUtils.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/DataTypeUtils.java @@ -29,7 +29,6 @@ import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; -import javax.annotation.Nonnull; import java.util.List; import java.util.Locale; import java.util.Optional; @@ -38,7 +37,6 @@ @API(API.Status.EXPERIMENTAL) public class DataTypeUtils { - @Nonnull private static final BiMap primitivesMap; /** @@ -49,8 +47,7 @@ public class DataTypeUtils { * @param type The Relational data type. * @return The corresponding Record Layer type. */ - @Nonnull - public static DataType toRelationalType(@Nonnull final Type type) { + public static DataType toRelationalType(final Type type) { if (primitivesMap.containsValue(type)) { return primitivesMap.inverse().get(type); } @@ -100,8 +97,7 @@ final var record = (Type.Record) type; */ @SpotBugsSuppressWarnings(value = {"NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE"}, justification = "should never happen, there is failUnchecked directly before that.") - @Nonnull - public static Type toRecordLayerType(@Nonnull final DataType type) { + public static Type toRecordLayerType(final DataType type) { if (primitivesMap.containsKey(type)) { return primitivesMap.get(type); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/NoOpSchemaTemplate.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/NoOpSchemaTemplate.java index a78a3dedd8a..4cbed26db54 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/NoOpSchemaTemplate.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/NoOpSchemaTemplate.java @@ -33,7 +33,6 @@ import com.apple.foundationdb.relational.api.metadata.View; import com.google.common.collect.Multimap; -import javax.annotation.Nonnull; import java.util.BitSet; import java.util.Collection; import java.util.Map; @@ -45,16 +44,14 @@ */ @API(API.Status.EXPERIMENTAL) public class NoOpSchemaTemplate implements SchemaTemplate { - @Nonnull private final String name; private final int version; - public NoOpSchemaTemplate(@Nonnull String name, int version) { + public NoOpSchemaTemplate(String name, int version) { this.name = name; this.version = version; } - @Nonnull @Override public String getName() { return name; @@ -75,87 +72,73 @@ public boolean isStoreRowVersions() { return false; } - @Nonnull @Override - public Schema generateSchema(@Nonnull final String databaseId, @Nonnull final String schemaName) { + public Schema generateSchema(final String databaseId, final String schemaName) { return new RecordLayerSchema(schemaName, databaseId, this); } - @Nonnull @Override public Set getTables() throws RelationalException { throw new RelationalException("NoOpSchemaTemplate doesn't have tables!", ErrorCode.INVALID_PARAMETER); } - @Nonnull @Override public Set getViews() throws RelationalException { throw new RelationalException("NoOpSchemaTemplate doesn't have views!", ErrorCode.INVALID_PARAMETER); } - @Nonnull @Override - public Optional findTableByName(@Nonnull final String tableName) throws RelationalException { + public Optional
findTableByName(final String tableName) throws RelationalException { throw new RelationalException("NoOpSchemaTemplate doesn't have tables!", ErrorCode.INVALID_PARAMETER); } - @Nonnull @Override - public Optional findViewByName(@Nonnull final String viewName) throws RelationalException { + public Optional findViewByName(final String viewName) throws RelationalException { throw new RelationalException("NoOpSchemaTemplate doesn't have views!", ErrorCode.INVALID_PARAMETER); } - @Nonnull @Override public Multimap getTableIndexMapping() throws RelationalException { throw new RelationalException("NoOpSchemaTemplate doesn't have indexes!", ErrorCode.INVALID_PARAMETER); } - @Nonnull @Override public Set getIndexes() throws RelationalException { throw new RelationalException("NoOpSchemaTemplate doesn't have indexes!", ErrorCode.INVALID_PARAMETER); } - @Nonnull @Override - public BitSet getIndexEntriesAsBitset(@Nonnull final Optional> readableIndexNames) throws RelationalException { + public BitSet getIndexEntriesAsBitset(final Optional> readableIndexNames) throws RelationalException { throw new RelationalException("NoOpSchemaTemplate doesn't have indexes!", ErrorCode.INVALID_PARAMETER); } - @Nonnull @Override public Set getInvokedRoutines() throws RelationalException { throw new RelationalException("NoOpSchemaTemplate doesn't have invoked routines!", ErrorCode.INVALID_PARAMETER); } - @Nonnull @Override - public Optional findInvokedRoutineByName(@Nonnull final String routineName) throws RelationalException { + public Optional findInvokedRoutineByName(final String routineName) throws RelationalException { throw new RelationalException("NoOpSchemaTemplate doesn't have invoked routines!", ErrorCode.INVALID_PARAMETER); } - @Nonnull @Override public Collection getTemporaryInvokedRoutines() throws RelationalException { throw new RelationalException("NoOpSchemaTemplate doesn't have temporary invoked routines!", ErrorCode.INVALID_PARAMETER); } - @Nonnull @Override public Map getStoredQueries() throws RelationalException { throw new RelationalException("NoOpSchemaTemplate doesn't have stored queries!", ErrorCode.INVALID_PARAMETER); } - @Nonnull @Override public String getTransactionBoundMetadataAsString() throws RelationalException { throw new RelationalException("NoOpSchemaTemplate doesn't have temporary invoked routines!", ErrorCode.INVALID_PARAMETER); } - @Nonnull @Override - public T unwrap(@Nonnull final Class iface) throws RelationalException { + public T unwrap(final Class iface) throws RelationalException { return iface.cast(this); } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerColumn.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerColumn.java index f6d1d1719c3..6b630cc7363 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerColumn.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerColumn.java @@ -26,32 +26,27 @@ import com.apple.foundationdb.relational.api.metadata.DataType; import com.apple.foundationdb.relational.util.Assert; -import javax.annotation.Nonnull; import java.util.Objects; @API(API.Status.EXPERIMENTAL) public class RecordLayerColumn implements Column { - @Nonnull private final String name; - @Nonnull private final DataType dataType; private final int index; - RecordLayerColumn(@Nonnull String name, @Nonnull DataType dataType, int index) { + RecordLayerColumn(String name, DataType dataType, int index) { this.name = name; this.dataType = dataType; this.index = index; } - @Nonnull @Override public DataType getDataType() { return dataType; } - @Nonnull @Override public String getName() { return name; @@ -93,19 +88,16 @@ private Builder() { this.index = -1; } - @Nonnull public Builder setName(String name) { this.name = name; return this; } - @Nonnull - public Builder setDataType(@Nonnull final DataType dataType) { + public Builder setDataType(final DataType dataType) { this.dataType = dataType; return this; } - @Nonnull public Builder setIndex(int index) { Assert.thatUnchecked(index >= 0); this.index = index; @@ -117,12 +109,10 @@ public RecordLayerColumn build() { } } - @Nonnull - public static RecordLayerColumn from(@Nonnull final DataType.StructType.Field field) { + public static RecordLayerColumn from(final DataType.StructType.Field field) { return new RecordLayerColumn(field.getName(), field.getType(), field.getIndex()); } - @Nonnull public static RecordLayerColumn.Builder newBuilder() { return new Builder(); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerIndex.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerIndex.java index 323c8720960..31e5471b5b2 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerIndex.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerIndex.java @@ -21,7 +21,6 @@ package com.apple.foundationdb.relational.recordlayer.metadata; import com.apple.foundationdb.annotation.API; -import com.apple.foundationdb.record.RecordMetaDataProto; import com.apple.foundationdb.record.metadata.IndexOptions; import com.apple.foundationdb.record.metadata.expressions.KeyExpression; import com.apple.foundationdb.record.query.plan.cascades.typing.Type; @@ -30,41 +29,37 @@ import com.apple.foundationdb.relational.util.Assert; import com.google.common.collect.ImmutableMap; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.Map; import java.util.Objects; +import static com.apple.foundationdb.record.RecordMetaDataProto.Predicate; + @API(API.Status.EXPERIMENTAL) public final class RecordLayerIndex implements Index { - @Nonnull private final String tableName; - @Nonnull private final String tableStorageName; private final String indexType; - @Nonnull private final String name; - @Nonnull private final KeyExpression keyExpression; - @Nonnull private final Map options; @Nullable - private final RecordMetaDataProto.Predicate predicate; - - private RecordLayerIndex(@Nonnull final String tableName, - @Nonnull final String tableStorageName, - @Nonnull final String indexType, - @Nonnull final String name, - @Nonnull final KeyExpression keyExpression, - @Nullable final RecordMetaDataProto.Predicate predicate, - @Nonnull final Map options) { + private final Predicate predicate; + + private RecordLayerIndex(final String tableName, + final String tableStorageName, + final String indexType, + final String name, + final KeyExpression keyExpression, + @Nullable final Predicate predicate, + final Map options) { this.tableName = tableName; this.tableStorageName = tableStorageName; this.indexType = indexType; @@ -74,18 +69,15 @@ private RecordLayerIndex(@Nonnull final String tableName, this.options = ImmutableMap.copyOf(options); } - @Nonnull @Override public String getTableName() { return tableName; } - @Nonnull public String getTableStorageName() { return tableStorageName; } - @Nonnull @Override public String getIndexType() { return indexType; @@ -103,28 +95,24 @@ public boolean isSparse() { } @Nullable - public RecordMetaDataProto.Predicate getPredicate() { + public Predicate getPredicate() { return predicate; } - @Nonnull @Override public String getName() { return name; } - @Nonnull public KeyExpression getKeyExpression() { return keyExpression; } - @Nonnull public Map getOptions() { return options; } - @Nonnull - public static RecordLayerIndex from(@Nonnull final String tableName, @Nonnull String tableStorageName, @Nonnull final com.apple.foundationdb.record.metadata.Index index) { + public static RecordLayerIndex from(final String tableName, String tableStorageName, final com.apple.foundationdb.record.metadata.Index index) { return newBuilder() .setName(index.getName()) .setIndexType(index.getType()) @@ -164,68 +152,57 @@ public static class Builder { private String indexType; private String name; private KeyExpression keyExpression; - @Nullable - private ImmutableMap.Builder optionsBuilder; + private ImmutableMap.@Nullable Builder optionsBuilder; @Nullable - private RecordMetaDataProto.Predicate predicate; + private Predicate predicate; - @Nonnull public Builder setTableName(String tableName) { this.tableName = tableName; return this; } - @Nonnull public Builder setTableStorageName(String tableStorageName) { this.tableStorageName = tableStorageName; return this; } - @Nonnull - public Builder setTableType(@Nonnull Type.Record tableType) { + public Builder setTableType(Type.Record tableType) { return setTableName(tableType.getName()) .setTableStorageName(tableType.getStorageName()); } - @Nonnull public Builder setIndexType(String indexType) { this.indexType = indexType; return this; } - @Nonnull public Builder setName(String name) { this.name = name; return this; } - @Nonnull public Builder setKeyExpression(KeyExpression keyExpression) { this.keyExpression = keyExpression; return this; } - @Nonnull - public Builder setPredicate(@Nullable final RecordMetaDataProto.Predicate predicate) { + public Builder setPredicate(@Nullable final Predicate predicate) { this.predicate = predicate; return this; } - @Nonnull public Builder setUnique(boolean isUnique) { return setOption(IndexOptions.UNIQUE_OPTION, isUnique); } - @Nonnull - public Builder setOptions(@Nonnull final Map options) { + public Builder setOptions(final Map options) { optionsBuilder = ImmutableMap.builderWithExpectedSize(options.size()); optionsBuilder.putAll(options); return this; } - @Nonnull - public Builder addAllOptions(@Nonnull final Map options) { + public Builder addAllOptions(final Map options) { if (optionsBuilder == null) { optionsBuilder = ImmutableMap.builder(); } @@ -233,8 +210,7 @@ public Builder addAllOptions(@Nonnull final Map options) { return this; } - @Nonnull - public Builder setOption(@Nonnull final String optionKey, @Nonnull final String optionValue) { + public Builder setOption(final String optionKey, final String optionValue) { if (optionsBuilder == null) { optionsBuilder = ImmutableMap.builder(); } @@ -242,17 +218,14 @@ public Builder setOption(@Nonnull final String optionKey, @Nonnull final String return this; } - @Nonnull - public Builder setOption(@Nonnull final String optionKey, int optionValue) { + public Builder setOption(final String optionKey, int optionValue) { return setOption(optionKey, Integer.toString(optionValue)); } - @Nonnull - public Builder setOption(@Nonnull final String optionKey, boolean optionValue) { + public Builder setOption(final String optionKey, boolean optionValue) { return setOption(optionKey, Boolean.toString(optionValue)); } - @Nonnull public RecordLayerIndex build() { Assert.notNullUnchecked(name, "index name is not set"); Assert.notNullUnchecked(tableName, "table name is not set"); @@ -266,7 +239,6 @@ public RecordLayerIndex build() { } } - @Nonnull public static Builder newBuilder() { return new Builder(); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java index 4df8a18d5ca..fea9b1783b9 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java @@ -26,39 +26,32 @@ import com.apple.foundationdb.relational.recordlayer.util.MemoizedFunction; import com.apple.foundationdb.relational.util.Assert; -import javax.annotation.Nonnull; import java.util.Objects; import java.util.function.Function; public class RecordLayerInvokedRoutine implements InvokedRoutine { - @Nonnull private final String description; - @Nonnull private final String normalizedDescription; - @Nonnull private final PreparedParams preparedParams; - @Nonnull private final String name; private final boolean isTemporary; - @Nonnull private final Function userDefinedFunctionProvider; - @Nonnull private final UserDefinedFunction serializableFunction; - public RecordLayerInvokedRoutine(@Nonnull final String description, - @Nonnull final String normalizedDescription, - @Nonnull final String name, - @Nonnull final PreparedParams preparedParams, + public RecordLayerInvokedRoutine(final String description, + final String normalizedDescription, + final String name, + final PreparedParams preparedParams, boolean isTemporary, - @Nonnull final Function userDefinedFunctionProvider, - @Nonnull final UserDefinedFunction serializableFunction) { + final Function userDefinedFunctionProvider, + final UserDefinedFunction serializableFunction) { this.description = description; this.normalizedDescription = normalizedDescription; this.name = name; @@ -68,40 +61,33 @@ public RecordLayerInvokedRoutine(@Nonnull final String description, this.serializableFunction = serializableFunction; } - @Nonnull @Override public String getDescription() { return description; } - @Nonnull @Override public String getNormalizedDescription() { return normalizedDescription; } - @Nonnull public PreparedParams getPreparedParams() { return preparedParams; } - @Nonnull public Function getUserDefinedFunctionProvider() { return userDefinedFunctionProvider; } - @Nonnull @Override public String getName() { return name; } - @Nonnull public static Builder newBuilder() { return new Builder(); } - @Nonnull public UserDefinedFunction asSerializableFunction() { return serializableFunction; } @@ -133,7 +119,6 @@ public String toString() { return "invoked routine (name '" + name + "', description '" + description + "')"; } - @Nonnull public Builder toBuilder() { return newBuilder() .setName(getName()) @@ -156,49 +141,41 @@ public static final class Builder { private Builder() { } - @Nonnull - public Builder setDescription(@Nonnull final String description) { + public Builder setDescription(final String description) { this.description = description; return this; } - @Nonnull - public Builder setNormalizedDescription(@Nonnull final String normalizedDescription) { + public Builder setNormalizedDescription(final String normalizedDescription) { this.normalizedDescription = normalizedDescription; return this; } - @Nonnull - public Builder setName(@Nonnull final String name) { + public Builder setName(final String name) { this.name = name; return this; } - @Nonnull - public Builder withUserDefinedFunctionProvider(@Nonnull final Function userDefinedFunctionProvider) { + public Builder withUserDefinedFunctionProvider(final Function userDefinedFunctionProvider) { this.userDefinedFunctionProvider = userDefinedFunctionProvider; return this; } - @Nonnull - public Builder withSerializableFunction(@Nonnull final UserDefinedFunction serializableFunction) { + public Builder withSerializableFunction(final UserDefinedFunction serializableFunction) { this.serializableFunction = serializableFunction; return this; } - @Nonnull - public Builder setPreparedParams(@Nonnull final PreparedParams preparedParams) { + public Builder setPreparedParams(final PreparedParams preparedParams) { this.preparedParams = preparedParams; return this; } - @Nonnull public Builder setTemporary(boolean isTemporary) { this.isTemporary = isTemporary; return this; } - @Nonnull public RecordLayerInvokedRoutine build() { Assert.notNullUnchecked(name); Assert.notNullUnchecked(description); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerSchema.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerSchema.java index 3b4fa2fa248..822d19803ab 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerSchema.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerSchema.java @@ -25,18 +25,14 @@ import com.apple.foundationdb.relational.api.metadata.Schema; import com.apple.foundationdb.relational.api.metadata.SchemaTemplate; -import javax.annotation.Nonnull; @API(API.Status.EXPERIMENTAL) public class RecordLayerSchema implements Schema { - @Nonnull private final String name; - @Nonnull private final SchemaTemplate schemaTemplate; - @Nonnull private final String databaseName; /** @@ -46,27 +42,24 @@ public class RecordLayerSchema implements Schema { * @param databaseName The database name to which the schema belongs. * @param schemaTemplate The name of the originating schema template. */ - RecordLayerSchema(@Nonnull final String name, - @Nonnull final String databaseName, - @Nonnull final SchemaTemplate schemaTemplate) { + RecordLayerSchema(final String name, + final String databaseName, + final SchemaTemplate schemaTemplate) { this.name = name; this.databaseName = databaseName; this.schemaTemplate = schemaTemplate; } - @Nonnull @Override public String getName() { return name; } - @Nonnull @Override public SchemaTemplate getSchemaTemplate() { return schemaTemplate; } - @Nonnull @Override public String getDatabaseName() { return databaseName; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerSchemaTemplate.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerSchemaTemplate.java index b8717bcec7a..bdc5a53f076 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerSchemaTemplate.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerSchemaTemplate.java @@ -50,7 +50,6 @@ import com.google.common.collect.Multimap; import com.google.protobuf.Descriptors; -import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.BitSet; import java.util.Collection; @@ -69,19 +68,14 @@ @API(API.Status.EXPERIMENTAL) public final class RecordLayerSchemaTemplate implements SchemaTemplate { - @Nonnull private final String name; - @Nonnull private final Set tables; - @Nonnull private final Set invokedRoutines; - @Nonnull private final Set views; - @Nonnull private final Map storedQueries; private final int version; @@ -90,28 +84,23 @@ public final class RecordLayerSchemaTemplate implements SchemaTemplate { private final boolean storeRowVersions; - @Nonnull private final Supplier metaDataSupplier; - @Nonnull private final Supplier> tableIndexMappingSupplier; - @Nonnull private final Supplier> indexesSupplier; - @Nonnull private final Supplier> temporaryInvokedRoutinesSupplier; - @Nonnull private final Supplier transactionBoundMetadataSupplier; private final boolean intermingleTables; - private RecordLayerSchemaTemplate(@Nonnull final String name, - @Nonnull final Set tables, - @Nonnull final Set invokedRoutines, - @Nonnull final Set views, - @Nonnull final Map storedQueries, + private RecordLayerSchemaTemplate(final String name, + final Set tables, + final Set invokedRoutines, + final Set views, + final Map storedQueries, int version, boolean enableLongRows, boolean storeRowVersions, @@ -132,16 +121,16 @@ private RecordLayerSchemaTemplate(@Nonnull final String name, this.transactionBoundMetadataSupplier = Suppliers.memoize(this::computeTransactionBoundMetadata); } - private RecordLayerSchemaTemplate(@Nonnull final String name, - @Nonnull final Set tables, - @Nonnull final Set invokedRoutines, - @Nonnull final Set views, - @Nonnull final Map storedQueries, + private RecordLayerSchemaTemplate(final String name, + final Set tables, + final Set invokedRoutines, + final Set views, + final Map storedQueries, int version, boolean enableLongRows, boolean storeRowVersions, boolean intermingleTables, - @Nonnull final RecordMetaData cachedMetadata) { + final RecordMetaData cachedMetadata) { this.name = name; this.version = version; this.tables = ImmutableSet.copyOf(tables); @@ -158,7 +147,6 @@ private RecordLayerSchemaTemplate(@Nonnull final String name, this.transactionBoundMetadataSupplier = Suppliers.memoize(this::computeTransactionBoundMetadata); } - @Nonnull @Override public String getName() { return name; @@ -184,24 +172,20 @@ public boolean isIntermingleTables() { return intermingleTables; } - @Nonnull @Override public Set getTables() { return tables; } - @Nonnull @Override - public RecordLayerSchema generateSchema(@Nonnull String databaseId, @Nonnull String schemaName) { + public RecordLayerSchema generateSchema(String databaseId, String schemaName) { return new RecordLayerSchema(schemaName, databaseId, this); } - @Nonnull - public Descriptors.Descriptor getDescriptor(@Nonnull final String tableName) { + public Descriptors.Descriptor getDescriptor(final String tableName) { return toRecordMetadata().getRecordType(tableName).getDescriptor(); } - @Nonnull private RecordMetaData buildRecordMetadata() { final var fileDescriptorProtoSerializer = new FileDescriptorSerializer(); accept(fileDescriptorProtoSerializer); @@ -219,7 +203,6 @@ private RecordMetaData buildRecordMetadata() { return recordMetadataSerializer.getBuilder().build(); } - @Nonnull public RecordMetaData toRecordMetadata() { return metaDataSupplier.get(); } @@ -231,9 +214,8 @@ public RecordMetaData toRecordMetadata() { * @param version The version of the metadata. * @return A {@link RecordLayerSchemaTemplate} instance of the deserialized metadata. */ - @Nonnull - public static RecordLayerSchemaTemplate fromRecordMetadata(@Nonnull final RecordMetaData metaData, - @Nonnull final String templateName, + public static RecordLayerSchemaTemplate fromRecordMetadata(final RecordMetaData metaData, + final String templateName, int version) { final var deserializer = new RecordMetadataDeserializer(metaData); return deserializer.getSchemaTemplate(templateName, version); @@ -245,9 +227,8 @@ public static RecordLayerSchemaTemplate fromRecordMetadata(@Nonnull final Record * @param tableName The name of the {@link Table}. * @return An {@link Optional} containing the {@link Table} if it is found, otherwise {@code Empty}. */ - @Nonnull @Override - public Optional
findTableByName(@Nonnull final String tableName) { + public Optional
findTableByName(final String tableName) { for (final var table : getTables()) { if (table.getName().equals(tableName)) { return Optional.of(table); @@ -256,7 +237,6 @@ public Optional
findTableByName(@Nonnull final String tableName) { return Optional.empty(); } - @Nonnull private Multimap computeTableIndexMapping() { final var result = ImmutableSetMultimap.builder(); for (final var table : getTables()) { @@ -272,13 +252,11 @@ private Multimap computeTableIndexMapping() { * * @return a multi-map whose key is the {@link Table} name, and value(s) is the {@link Index}. */ - @Nonnull @Override public Multimap getTableIndexMapping() { return tableIndexMappingSupplier.get(); } - @Nonnull private Set computeIndexes() { final Set result = new TreeSet<>(); @@ -294,15 +272,13 @@ private Set computeIndexes() { return result; } - @Nonnull @Override public Set getIndexes() throws RelationalException { return indexesSupplier.get(); } - @Nonnull @Override - public BitSet getIndexEntriesAsBitset(@Nonnull final Optional> indexNames) throws RelationalException { + public BitSet getIndexEntriesAsBitset(final Optional> indexNames) throws RelationalException { final var indexSet = getIndexes(); // sorted (50) final var result = new BitSet(indexSet.size()); if (indexNames.isEmpty()) { // all indexes are readable. @@ -328,68 +304,58 @@ public BitSet getIndexEntriesAsBitset(@Nonnull final Optional> index return result; } - @Nonnull @Override public Set getInvokedRoutines() { return invokedRoutines; } - @Nonnull @Override - public Optional findInvokedRoutineByName(@Nonnull final String routineName) { + public Optional findInvokedRoutineByName(final String routineName) { return invokedRoutines.stream().filter(routine -> routine.getName().equals(routineName)).findFirst(); } - @Nonnull @Override public Set getViews() { return views; } - @Nonnull @Override public Map getStoredQueries() { return storedQueries; } - @Nonnull @Override - public Optional findViewByName(@Nonnull final String viewName) { + public Optional findViewByName(final String viewName) { return views.stream().filter(view -> view.getName().equals(viewName)).findFirst(); } - @Nonnull private Collection computeTemporaryInvokedRoutines() { return invokedRoutines.stream().filter(RecordLayerInvokedRoutine::isTemporary) .sorted(Comparator.comparing(RecordLayerInvokedRoutine::getDescription)).collect(ImmutableList.toImmutableList()); } - @Nonnull @Override public Collection getTemporaryInvokedRoutines() { return temporaryInvokedRoutinesSupplier.get(); } - @Nonnull private String computeTransactionBoundMetadata() { return getTemporaryInvokedRoutines().stream().map(InvokedRoutine::getNormalizedDescription) .collect(Collectors.joining("||")); } - @Nonnull @Override public String getTransactionBoundMetadataAsString() { return transactionBoundMetadataSupplier.get(); } - @Nonnull @Override - public T unwrap(@Nonnull final Class iface) throws RelationalException { + public T unwrap(final Class iface) throws RelationalException { return iface.cast(this); } @Override - public void accept(@Nonnull final Visitor visitor) { + public void accept(final Visitor visitor) { visitor.startVisit(this); visitor.visit(this); for (final var table : getTables()) { @@ -416,19 +382,14 @@ public static final class Builder { private boolean storeRowVersions; - @Nonnull private final Map tables; - @Nonnull private final Map auxiliaryTypes; // for quick lookup - @Nonnull private final Map invokedRoutines; - @Nonnull private final Map views; - @Nonnull private final Map storedQueries; @@ -444,25 +405,21 @@ private Builder() { enableLongRows = true; } - @Nonnull public Builder setName(String name) { this.name = name; return this; } - @Nonnull public Builder setVersion(int version) { this.version = version; return this; } - @Nonnull public Builder setEnableLongRows(boolean value) { this.enableLongRows = value; return this; } - @Nonnull public Builder setIntermingleTables(boolean intermingleTables) { this.intermingleTables = intermingleTables; return this; @@ -472,14 +429,12 @@ public boolean isIntermingleTables() { return intermingleTables; } - @Nonnull public Builder setStoreRowVersions(boolean value) { this.storeRowVersions = value; return this; } - @Nonnull - public Builder addTable(@Nonnull RecordLayerTable table) { + public Builder addTable(RecordLayerTable table) { verifyNameIsNotUsed(table.getName()); if (!intermingleTables) { Assert.thatUnchecked(Key.Expressions.recordType().isPrefixKey(table.getPrimaryKey()), @@ -489,26 +444,22 @@ public Builder addTable(@Nonnull RecordLayerTable table) { return this; } - @Nonnull - public Builder addTables(@Nonnull final Collection tables) { + public Builder addTables(final Collection tables) { tables.forEach(this::addTable); return this; } - @Nonnull - public Builder addInvokedRoutine(@Nonnull final RecordLayerInvokedRoutine invokedRoutine) { + public Builder addInvokedRoutine(final RecordLayerInvokedRoutine invokedRoutine) { verifyNameIsNotUsed(invokedRoutine.getName()); invokedRoutines.put(invokedRoutine.getName(), invokedRoutine); return this; } - @Nonnull public List getInvokedRoutines() { return ImmutableList.copyOf(invokedRoutines.values()); } - @Nonnull - public Builder replaceInvokedRoutine(@Nonnull final RecordLayerInvokedRoutine invokedRoutine) { + public Builder replaceInvokedRoutine(final RecordLayerInvokedRoutine invokedRoutine) { if (invokedRoutines.containsKey(invokedRoutine.getName())) { Assert.thatUnchecked(invokedRoutines.get(invokedRoutine.getName()).isTemporary(), ErrorCode.INVALID_FUNCTION_DEFINITION, "attempt to replace non-temporary invoked routine!"); @@ -517,7 +468,7 @@ public Builder replaceInvokedRoutine(@Nonnull final RecordLayerInvokedRoutine in return this; } - public Builder removeInvokedRoutine(@Nonnull final String invokedRoutineName) { + public Builder removeInvokedRoutine(final String invokedRoutineName) { if (!invokedRoutines.containsKey(invokedRoutineName)) { Assert.thatUnchecked(invokedRoutines.get(invokedRoutineName).isTemporary(), ErrorCode.UNDEFINED_FUNCTION, "attempt to non-existent temporary invoked routine!"); @@ -526,47 +477,41 @@ public Builder removeInvokedRoutine(@Nonnull final String invokedRoutineName) { return this; } - @Nonnull - public Builder addInvokedRoutines(@Nonnull final Collection invokedRoutines) { + public Builder addInvokedRoutines(final Collection invokedRoutines) { invokedRoutines.forEach(this::addInvokedRoutine); return this; } - @Nonnull - public Builder addView(@Nonnull final RecordLayerView view) { + public Builder addView(final RecordLayerView view) { verifyNameIsNotUsed(view.getName()); views.put(view.getName(), view); return this; } - @Nonnull - public Builder replaceView(@Nonnull final RecordLayerView view) { + public Builder replaceView(final RecordLayerView view) { views.put(view.getName(), view); return this; } - public Builder removeView(@Nonnull final String viewName) { + public Builder removeView(final String viewName) { Assert.thatUnchecked(views.containsKey(viewName), ErrorCode.UNDEFINED_TABLE, "attempt to remove non-existent view!"); views.remove(viewName); return this; } - @Nonnull - public Builder addViews(@Nonnull final Collection views) { + public Builder addViews(final Collection views) { views.forEach(this::addView); return this; } - @Nonnull - public Builder addStoredQuery(@Nonnull final String name, @Nonnull final String storedQuery, - @Nonnull final List tempFunctions) { + public Builder addStoredQuery(final String name, final String storedQuery, + final List tempFunctions) { storedQueries.put(name, new StoredQuery(storedQuery, tempFunctions)); return this; } - @Nonnull - public Builder addStoredQueries(@Nonnull final Map storedQueries) { + public Builder addStoredQueries(final Map storedQueries) { this.storedQueries.putAll(storedQueries); return this; } @@ -579,8 +524,7 @@ public Builder addStoredQueries(@Nonnull final Map storedQu * @param auxiliaryType The auxiliary {@link DataType} to add. * @return {@code this} {@link Builder}. */ - @Nonnull - public Builder addAuxiliaryType(@Nonnull DataType.Named auxiliaryType) { + public Builder addAuxiliaryType(DataType.Named auxiliaryType) { verifyNameIsNotUsed(auxiliaryType.getName()); auxiliaryTypes.put(auxiliaryType.getName(), auxiliaryType); return this; @@ -594,33 +538,28 @@ public Builder addAuxiliaryType(@Nonnull DataType.Named auxiliaryType) { * @param auxiliaryTypes The auxiliary {@link DataType}s to add. * @return {@code this} {@link Builder}. */ - @Nonnull - public Builder addAuxiliaryTypes(@Nonnull Collection auxiliaryTypes) { + public Builder addAuxiliaryTypes(Collection auxiliaryTypes) { auxiliaryTypes.forEach(this::addAuxiliaryType); return this; } - @Nonnull - public Builder setCachedMetadata(@Nonnull final RecordMetaData metadata) { + public Builder setCachedMetadata(final RecordMetaData metadata) { this.cachedMetadata = metadata; return this; } - @Nonnull - public RecordLayerTable findTableByStorageName(@Nonnull final String storageName) { + public RecordLayerTable findTableByStorageName(final String storageName) { return tables.values().stream().filter(t -> t.getType().getStorageName().equals(storageName)) .findAny() .orElseThrow(() -> Assert.failUnchecked(ErrorCode.UNDEFINED_TABLE, "could not find '" + storageName + "'")); } - @Nonnull - public RecordLayerTable extractTable(@Nonnull final String name) { + public RecordLayerTable extractTable(final String name) { Assert.thatUnchecked(tables.containsKey(name), ErrorCode.UNDEFINED_TABLE, "could not find '%s'", name); return tables.remove(name); } - @Nonnull - public Optional findType(@Nonnull final String name) { + public Optional findType(final String name) { // we should also check whether the name exists in _both_ databases. if (tables.containsKey(name)) { return Optional.of(tables.get(name).getDatatype()); @@ -633,7 +572,6 @@ public Optional findType(@Nonnull final String name) { return Optional.empty(); } - @Nonnull public RecordLayerSchemaTemplate build() { Assert.thatUnchecked(!tables.isEmpty(), ErrorCode.INVALID_SCHEMA_TEMPLATE, "schema template contains no tables"); @@ -740,15 +678,14 @@ private void resolveTypes() { auxiliaryTypes.putAll(resolvedAuxiliaryTypes.build()); } - private void verifyNameIsNotUsed(@Nonnull final String name) { + private void verifyNameIsNotUsed(final String name) { Assert.thatUnchecked(!tables.containsKey(name), ErrorCode.INVALID_SCHEMA_TEMPLATE, () -> "table with name '" + name + "' already exists"); Assert.thatUnchecked(!auxiliaryTypes.containsKey(name), ErrorCode.INVALID_SCHEMA_TEMPLATE, () -> "type with name '" + name + "' already exists"); Assert.thatUnchecked(!invokedRoutines.containsKey(name), ErrorCode.INVALID_SCHEMA_TEMPLATE, () -> "routine with name '" + name + "' already exists"); Assert.thatUnchecked(!views.containsKey(name), ErrorCode.INVALID_SCHEMA_TEMPLATE, () -> "view with name '" + name + "' already exists"); } - @Nonnull - private static Set getDependencies(@Nonnull final DataType dataType, @Nonnull final Map types) { + private static Set getDependencies(final DataType dataType, final Map types) { // TODO (yhatem) I think this doesn't work in case of recursive types. // moreover, this does not work with inlined types, but this is ok since we don't support them anyway. switch (dataType.getCode()) { @@ -780,12 +717,10 @@ private static Set getDependencies(@Nonnull final DataType dataType, @ } } - @Nonnull public static Builder newBuilder() { return new Builder(); } - @Nonnull public Builder toBuilder() { return newBuilder() .setName(name) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerTable.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerTable.java index 78447417991..6db70121ae0 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerTable.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerTable.java @@ -39,8 +39,7 @@ import com.google.common.collect.ImmutableSet; import com.google.protobuf.DescriptorProtos; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; @@ -52,40 +51,36 @@ import java.util.Set; import java.util.stream.Collectors; +import static com.apple.foundationdb.record.query.plan.cascades.typing.Type.Record; +import static com.apple.foundationdb.record.query.plan.cascades.typing.Type.Record.Field; + /** * Represents a {@link Table} that is backed by the Record Layer. */ @API(API.Status.EXPERIMENTAL) public final class RecordLayerTable implements Table { - @Nonnull private final String name; - @Nonnull private final List columns; - @Nonnull private final Set indexes; - @Nonnull private final KeyExpression primaryKey; - @Nonnull private final DataType.StructType dataType; - @Nonnull - private final Type.Record record; + private final Record record; - @Nonnull private final Map generations; - private RecordLayerTable(@Nonnull final String name, - @Nonnull final List columns, - @Nonnull final Set indexes, - @Nonnull final KeyExpression primaryKey, - @Nonnull final Map generations, + private RecordLayerTable(final String name, + final List columns, + final Set indexes, + final KeyExpression primaryKey, + final Map generations, final DataType.StructType dataType, - final Type.Record record) { + final Record record) { this.name = name; this.columns = ImmutableList.copyOf(columns); this.indexes = ImmutableSet.copyOf(indexes); @@ -95,42 +90,36 @@ private RecordLayerTable(@Nonnull final String name, this.record = record == null ? calculateRecordLayerType() : record; } - @Nonnull @Override public String getName() { return name; } - @Nonnull @Override public Set getIndexes() { return indexes; } - @Nonnull public Map getGenerations() { return generations; } - @Nonnull @Override public Collection getColumns() { return columns; } - @Nonnull - public Type.Record getType() { + public Record getType() { return record; } - @Nonnull public KeyExpression getPrimaryKey() { return primaryKey; } // TODO: remove @Override - public void accept(@Nonnull final Visitor visitor) { + public void accept(final Visitor visitor) { visitor.visit(this); for (final var index : getIndexes()) { @@ -142,12 +131,10 @@ public void accept(@Nonnull final Visitor visitor) { } } - @Nonnull - private Type.Record calculateRecordLayerType() { - return (Type.Record) DataTypeUtils.toRecordLayerType(getDatatype()); + private Record calculateRecordLayerType() { + return (Record) DataTypeUtils.toRecordLayerType(getDatatype()); } - @Nonnull private DataType.StructType calculateDataType() { final var columnTypes = ImmutableList.builder(); for (final var column : columns) { @@ -176,7 +163,6 @@ private DataType.StructType calculateDataType() { return DataType.StructType.from(getName(), columnTypes.build(), true); } - @Nonnull @Override public DataType.StructType getDatatype() { return dataType; @@ -207,21 +193,17 @@ public boolean equals(Object obj) { public static final class Builder { private String name; - @Nonnull private final Set indexes; - @Nonnull private final ImmutableList.Builder columns; - @Nonnull private List primaryKeyParts; - @Nonnull private final Map generations; private DataType.StructType dataType; - private Type.Record record; + private Record record; private Builder() { this.indexes = new LinkedHashSet<>(); @@ -232,54 +214,46 @@ private Builder() { this.primaryKeyParts.add(Key.Expressions.recordType()); } - @Nonnull public Builder setName(String name) { this.name = name; return this; } - @Nonnull - public Builder setDatatype(@Nonnull DataType.StructType dataType) { + public Builder setDatatype(DataType.StructType dataType) { this.dataType = dataType; return this; } - @Nonnull - public Builder setRecord(@Nonnull Type.Record record) { + public Builder setRecord(Record record) { this.record = record; return this; } - @Nonnull - public Builder addIndex(@Nonnull final RecordLayerIndex index) { + public Builder addIndex(final RecordLayerIndex index) { Assert.thatUnchecked(indexes.stream().noneMatch(i -> index.getName().equals(i.getName())), ErrorCode.INDEX_ALREADY_EXISTS, () -> "attempt to add duplicate index '%s'" + index.getName()); this.indexes.add(index); return this; } - @Nonnull - public Builder addIndexes(@Nonnull final Collection indexes) { + public Builder addIndexes(final Collection indexes) { indexes.forEach(this::addIndex); return this; } - @Nonnull - public Builder addGenerations(@Nonnull final Map generations) { + public Builder addGenerations(final Map generations) { generations.forEach(this::addGeneration); return this; } - @Nonnull - public Builder addGeneration(int number, @Nonnull DescriptorProtos.FieldOptions options) { + public Builder addGeneration(int number, DescriptorProtos.FieldOptions options) { Assert.thatUnchecked(!generations.containsKey(number), ErrorCode.TABLE_ALREADY_EXISTS, "Duplicate field number %d for generation of Table %s", number, name); Assert.thatUnchecked(!generations.containsValue(options), ErrorCode.TABLE_ALREADY_EXISTS, "Duplicated options for different generations of Table %s", name); generations.put(number, options); return this; } - @Nonnull - public Builder setPrimaryKey(@Nonnull final KeyExpression primaryKey) { + public Builder setPrimaryKey(final KeyExpression primaryKey) { if (primaryKey instanceof ThenKeyExpression) { this.primaryKeyParts = new ArrayList<>(((ThenKeyExpression) primaryKey).getChildren()); } else if (primaryKey instanceof EmptyKeyExpression) { @@ -291,38 +265,33 @@ public Builder setPrimaryKey(@Nonnull final KeyExpression primaryKey) { return this; } - @Nonnull - public Builder addPrimaryKeyPart(@Nonnull final List primaryKeyPart) { + public Builder addPrimaryKeyPart(final List primaryKeyPart) { primaryKeyParts.add(toKeyExpression(record, primaryKeyPart)); return this; } - @Nonnull - public Builder addColumn(@Nonnull final RecordLayerColumn column) { + public Builder addColumn(final RecordLayerColumn column) { columns.add(column); return this; } - @Nonnull - public Builder addColumns(@Nonnull final Collection columns) { + public Builder addColumns(final Collection columns) { this.columns.addAll(columns); return this; } - @Nonnull - private static KeyExpression toKeyExpression(@Nullable Type.Record type, @Nonnull final List fields) { + private static KeyExpression toKeyExpression(@Nullable Record type, final List fields) { Assert.thatUnchecked(!fields.isEmpty()); return toKeyExpression(type, fields.iterator()); } - @Nonnull - private static KeyExpression toKeyExpression(@Nullable Type.Record type, @Nonnull final Iterator fields) { + private static KeyExpression toKeyExpression(@Nullable Record type, final Iterator fields) { Assert.thatUnchecked(fields.hasNext()); String fieldName = fields.next(); - Type.Record.Field field = getFieldDefinition(type, fieldName); + Field field = getFieldDefinition(type, fieldName); final FieldKeyExpression expression = Key.Expressions.field(getFieldStorageName(field, fieldName)); if (fields.hasNext()) { - Type.Record fieldType = getFieldRecordType(type, field); + Record fieldType = getFieldRecordType(type, field); return expression.nest(toKeyExpression(fieldType, fields)); } else { return expression; @@ -330,28 +299,26 @@ private static KeyExpression toKeyExpression(@Nullable Type.Record type, @Nonnul } @Nullable - private static Type.Record.Field getFieldDefinition(@Nullable Type.Record type, @Nonnull String fieldName) { + private static Field getFieldDefinition(@Nullable Record type, String fieldName) { return type == null ? null : type.getFieldNameFieldMap().get(fieldName); } - @Nonnull - private static String getFieldStorageName(@Nullable Type.Record.Field field, @Nonnull String fieldName) { + private static String getFieldStorageName(@Nullable Field field, String fieldName) { return field == null ? ProtoUtils.toProtoBufCompliantName(fieldName) : field.getFieldStorageName(); } @Nullable - private static Type.Record getFieldRecordType(@Nullable Type.Record recordType, @Nullable Type.Record.Field field) { + private static Record getFieldRecordType(@Nullable Record recordType, @Nullable Field field) { if (field == null) { return null; } Type fieldType = field.getFieldType(); - if (!(fieldType instanceof Type.Record)) { + if (!(fieldType instanceof Record)) { Assert.failUnchecked(ErrorCode.INVALID_COLUMN_REFERENCE, "Field '" + field.getFieldName() + "' on type '" + (recordType == null ? "UNKNOWN" : recordType.getName()) + "' is not a struct"); } - return (Type.Record) fieldType; + return (Record) fieldType; } - @Nonnull private KeyExpression getPrimaryKey() { if (primaryKeyParts.isEmpty()) { return EmptyKeyExpression.EMPTY; @@ -362,7 +329,6 @@ private KeyExpression getPrimaryKey() { } } - @Nonnull public RecordLayerTable build() { Assert.notNullUnchecked(name, "table name is not set"); @@ -375,8 +341,7 @@ public RecordLayerTable build() { return new RecordLayerTable(name, columnsList, indexesSet, getPrimaryKey(), generations, dataType, record); } - @Nonnull - public static Builder from(@Nonnull final RecordLayerTable table) { + public static Builder from(final RecordLayerTable table) { return newBuilder(false) .setName(table.getName()) .addColumns(table.getColumns()) @@ -387,16 +352,14 @@ public static Builder from(@Nonnull final RecordLayerTable table) { .addGenerations(table.getGenerations()); } - @Nonnull - public static Builder from(@Nonnull final DataType.StructType structType) { + public static Builder from(final DataType.StructType structType) { return newBuilder(false) .setName(structType.getName()) .addColumns(structType.getFields().stream().map(RecordLayerColumn::from).collect(Collectors.toList())) .setDatatype(structType); } - @Nonnull - public static Builder from(@Nonnull final Type.Record record) { + public static Builder from(final Record record) { final var relationalType = DataTypeUtils.toRelationalType(record); Assert.thatUnchecked(relationalType instanceof DataType.StructType); final var asStruct = (DataType.StructType) relationalType; @@ -407,8 +370,7 @@ public static Builder from(@Nonnull final Type.Record record) { return from(asStruct).setRecord(record); } - @Nonnull - private static List normalize(@Nonnull final List columns) { + private static List normalize(final List columns) { if (columns.stream().allMatch(c -> c.getIndex() >= 0)) { return columns; } @@ -425,7 +387,6 @@ private static List normalize(@Nonnull final List 50000"). * This contains only the query portion, not the CREATE VIEW DDL statement. */ - @Nonnull private final String description; /** * The SQL name of the view as it appears in queries (e.g., "employee_view"). */ - @Nonnull private final String name; /** @@ -57,13 +54,12 @@ public class RecordLayerView implements com.apple.foundationdb.relational.api.me * The boolean parameter indicates whether to compile with the view with case-sensitive processing * of identifiers, see {@code Options.Name.CASE_SENSITIVE_IDENTIFIERS} for more information. */ - @Nonnull private final Function compilableViewSupplier; - public RecordLayerView(@Nonnull final String description, - @Nonnull final String name, + public RecordLayerView(final String description, + final String name, final boolean isTemporary, - @Nonnull final Function compilableViewSupplier) { + final Function compilableViewSupplier) { this.description = description; this.name = name; this.isTemporary = isTemporary; @@ -71,7 +67,6 @@ public RecordLayerView(@Nonnull final String description, } - @Nonnull @Override public String getDescription() { return description; @@ -82,23 +77,19 @@ public boolean isTemporary() { return isTemporary; } - @Nonnull public Function getCompilableViewSupplier() { return compilableViewSupplier; } - @Nonnull @Override public String getName() { return name; } - @Nonnull public static Builder newBuilder() { return new Builder(); } - @Nonnull public View asRawView() { return new View(getName(), getDescription()); } @@ -126,7 +117,6 @@ public String toString() { return "view (name '" + name + "', definition '" + description + "', temporary=" + isTemporary + ")"; } - @Nonnull public Builder toBuilder() { return newBuilder() .setName(getName()) @@ -144,31 +134,26 @@ public static final class Builder { private Builder() { } - @Nonnull - public Builder setDescription(@Nonnull final String description) { + public Builder setDescription(final String description) { this.description = description; return this; } - @Nonnull - public Builder setName(@Nonnull final String name) { + public Builder setName(final String name) { this.name = name; return this; } - @Nonnull public Builder setTemporary(boolean isTemporary) { this.isTemporary = isTemporary; return this; } - @Nonnull - public Builder setViewCompiler(@Nonnull final Function compilableViewSupplier) { + public Builder setViewCompiler(final Function compilableViewSupplier) { this.compilableViewSupplier = compilableViewSupplier; return this; } - @Nonnull public RecordLayerView build() { Assert.notNullUnchecked(name); Assert.notNullUnchecked(description); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/SkeletonVisitor.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/SkeletonVisitor.java index 89f438b208f..8b9b6c2f9a9 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/SkeletonVisitor.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/SkeletonVisitor.java @@ -31,7 +31,6 @@ import com.apple.foundationdb.relational.api.metadata.View; import com.apple.foundationdb.relational.api.metadata.Visitor; -import javax.annotation.Nonnull; /** * This is a no-op {@link Visitor} added to make convenient to implement other visitors @@ -40,47 +39,47 @@ @API(API.Status.EXPERIMENTAL) public class SkeletonVisitor implements Visitor { @Override - public void visit(@Nonnull final Table table) { + public void visit(final Table table) { // no-op } @Override - public void visit(@Nonnull final Column column) { + public void visit(final Column column) { // no-op } @Override - public void startVisit(@Nonnull final SchemaTemplate schemaTemplate) { + public void startVisit(final SchemaTemplate schemaTemplate) { // no-op } @Override - public void visit(@Nonnull final SchemaTemplate schemaTemplate) { + public void visit(final SchemaTemplate schemaTemplate) { // no-op } @Override - public void finishVisit(@Nonnull final SchemaTemplate schemaTemplate) { + public void finishVisit(final SchemaTemplate schemaTemplate) { // no-op } @Override - public void visit(@Nonnull final Schema schema) { + public void visit(final Schema schema) { // no-op } @Override - public void visit(@Nonnull final Index index) { + public void visit(final Index index) { // no-op } @Override - public void visit(@Nonnull final InvokedRoutine invokedRoutine) { + public void visit(final InvokedRoutine invokedRoutine) { // no-op } @Override - public void visit(@Nonnull final View view) { + public void visit(final View view) { // no-op } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/package-info.java index e0a5a4850c3..8fe8f1406dd 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/package-info.java @@ -22,4 +22,7 @@ * Metadata artefacts in Relational backed by Record Layer APIs. */ +@NullMarked package com.apple.foundationdb.relational.recordlayer.metadata; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/FileDescriptorSerializer.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/FileDescriptorSerializer.java index 68457e8a868..2195d6df01e 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/FileDescriptorSerializer.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/FileDescriptorSerializer.java @@ -33,7 +33,6 @@ import com.google.protobuf.DescriptorProtos; import com.google.protobuf.Descriptors; -import javax.annotation.Nonnull; import java.util.LinkedHashSet; import java.util.Locale; import java.util.Map; @@ -43,16 +42,12 @@ @API(API.Status.EXPERIMENTAL) public class FileDescriptorSerializer extends SkeletonVisitor { - @Nonnull private final DescriptorProtos.FileDescriptorProto.Builder fileBuilder; - @Nonnull private final DescriptorProtos.DescriptorProto.Builder unionDescriptorBuilder; - @Nonnull private final Set descriptorNames; - @Nonnull private final Set enumNames; // FileDescriptorSerializer operates in 2 modes. With `assignGenerations`=true, the serializer assumes that the @@ -71,7 +66,7 @@ public FileDescriptorSerializer() { this(DescriptorProtos.FileDescriptorProto.newBuilder()); } - public FileDescriptorSerializer(@Nonnull DescriptorProtos.FileDescriptorProto.Builder fileBuilder) { + public FileDescriptorSerializer(DescriptorProtos.FileDescriptorProto.Builder fileBuilder) { this.fileBuilder = fileBuilder; this.fileBuilder.addAllDependency(TypeRepository.DEPENDENCIES.stream().map(Descriptors.FileDescriptor::getFullName).collect(Collectors.toList())); this.unionDescriptorBuilder = DescriptorProtos.DescriptorProto.newBuilder().setName("RecordTypeUnion"); @@ -84,12 +79,12 @@ public FileDescriptorSerializer(@Nonnull DescriptorProtos.FileDescriptorProto.Bu } @Override - public void visit(@Nonnull Metadata metadata) { + public void visit(Metadata metadata) { Assert.failUnchecked(String.format(Locale.ROOT, "unexpected call on %s", metadata.getClass().getName())); } @Override - public void visit(@Nonnull final Table table) { + public void visit(final Table table) { Assert.thatUnchecked(table instanceof RecordLayerTable); final RecordLayerTable recordLayerTable = (RecordLayerTable) table; final Type.Record type = recordLayerTable.getType(); @@ -114,8 +109,7 @@ public void visit(@Nonnull final Table table) { } // (yhatem) this is temporary, we use rec layer typing also as a bridge to PB serialization for now. - @Nonnull - private String registerTypeDescriptors(@Nonnull final Type.Record type) { + private String registerTypeDescriptors(final Type.Record type) { final var builder = TypeRepository.newBuilder(); type.defineProtoType(builder); final var typeDescriptors = builder.build(); @@ -140,12 +134,12 @@ private String registerTypeDescriptors(@Nonnull final Type.Record type) { } @Override - public void startVisit(@Nonnull SchemaTemplate schemaTemplate) { + public void startVisit(SchemaTemplate schemaTemplate) { fileBuilder.setName(schemaTemplate.getName()); } @Override - public void finishVisit(@Nonnull SchemaTemplate schemaTemplate) { + public void finishVisit(SchemaTemplate schemaTemplate) { finish(); } @@ -154,12 +148,11 @@ private void finish() { fileBuilder.addMessageType(unionDescriptor); } - @Nonnull public DescriptorProtos.FileDescriptorProto.Builder getFileBuilder() { return fileBuilder; } - private void checkTableGenerations(@Nonnull Map generations) { + private void checkTableGenerations(Map generations) { // Determine the mode by generations map of the first table. if (assignGenerations == null) { assignGenerations = generations.isEmpty(); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/RecordMetadataDeserializer.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/RecordMetadataDeserializer.java index d3cc95a11d8..b06fbc66712 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/RecordMetadataDeserializer.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/RecordMetadataDeserializer.java @@ -42,7 +42,6 @@ import com.google.common.base.Suppliers; import com.google.protobuf.Descriptors; -import javax.annotation.Nonnull; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -57,24 +56,20 @@ @API(API.Status.EXPERIMENTAL) public class RecordMetadataDeserializer { - @Nonnull protected final RecordMetaData recordMetaData; - @Nonnull protected final RecordLayerSchemaTemplate.Builder builder; - public RecordMetadataDeserializer(@Nonnull final RecordMetaData recordMetaData) { + public RecordMetadataDeserializer(final RecordMetaData recordMetaData) { this.recordMetaData = recordMetaData; builder = deserializeRecordMetaData(recordMetaData); } - @Nonnull - public RecordLayerSchemaTemplate getSchemaTemplate(@Nonnull final String schemaTemplateName, int version) { + public RecordLayerSchemaTemplate getSchemaTemplate(final String schemaTemplateName, int version) { return builder.setName(schemaTemplateName).setVersion(version).build(); } - @Nonnull - private static RecordLayerSchemaTemplate.Builder deserializeRecordMetaData(@Nonnull final RecordMetaData recordMetaData) { + private static RecordLayerSchemaTemplate.Builder deserializeRecordMetaData(final RecordMetaData recordMetaData) { // iterate _only_ over the record types registered in the union descriptor to avoid potentially-expensive // deserialization of other descriptors that can never be used by the user. final var unionDescriptor = recordMetaData.getUnionDescriptor(); @@ -131,8 +126,7 @@ private static RecordLayerSchemaTemplate.Builder deserializeRecordMetaData(@Nonn return schemaTemplateBuilder; } - @Nonnull - private static RecordLayerTable.Builder generateTableBuilder(@Nonnull final RecordMetaData recordMetaData, @Nonnull final String userName, @Nonnull final String storageName) { + private static RecordLayerTable.Builder generateTableBuilder(final RecordMetaData recordMetaData, final String userName, final String storageName) { final RecordType recordType = recordMetaData.getRecordType(storageName); // todo (yhatem) we rely on the record type for deserialization from ProtoBuf for now, later on @@ -147,26 +141,23 @@ private static RecordLayerTable.Builder generateTableBuilder(@Nonnull final Reco .addIndexes(recordType.getIndexes().stream().map(index -> RecordLayerIndex.from(Objects.requireNonNull(recordLayerType.getName()), Objects.requireNonNull(recordLayerType.getStorageName()), index)).collect(Collectors.toSet())); } - @Nonnull @VisibleForTesting - protected static Function getSqlFunctionCompiler(@Nonnull final String name, - @Nonnull final Supplier metadata, - @Nonnull final String functionBody) { + protected static Function getSqlFunctionCompiler(final String name, + final Supplier metadata, + final String functionBody) { return isCaseSensitive -> RoutineParser.sqlFunctionParser(metadata.get()).parseFunction(functionBody, isCaseSensitive); } - @Nonnull @VisibleForTesting - protected static Function getViewCompiler(@Nonnull final String viewName, - @Nonnull final Supplier metadata, - @Nonnull final String viewDefinition) { + protected static Function getViewCompiler(final String viewName, + final Supplier metadata, + final String viewDefinition) { return isCaseSensitive -> RoutineParser.sqlFunctionParser(metadata.get()).parseView(viewName, viewDefinition, isCaseSensitive); } - @Nonnull - private static RecordLayerInvokedRoutine.Builder generateInvokedRoutineBuilder(@Nonnull final Supplier metadata, - @Nonnull final String name, - @Nonnull final String body) { + private static RecordLayerInvokedRoutine.Builder generateInvokedRoutineBuilder(final Supplier metadata, + final String name, + final String body) { return RecordLayerInvokedRoutine.newBuilder() .setName(name) .setDescription(body) @@ -175,10 +166,9 @@ private static RecordLayerInvokedRoutine.Builder generateInvokedRoutineBuilder(@ .withSerializableFunction(new RawSqlFunction(name, body)); } - @Nonnull - private static RecordLayerInvokedRoutine.Builder generateInvokedRoutineBuilder(@Nonnull final String name, - @Nonnull final String body, - @Nonnull final UserDefinedMacroFunction userDefinedScalarFunction) { + private static RecordLayerInvokedRoutine.Builder generateInvokedRoutineBuilder(final String name, + final String body, + final UserDefinedMacroFunction userDefinedScalarFunction) { return RecordLayerInvokedRoutine.newBuilder() .setName(name) .setDescription(body) @@ -186,18 +176,16 @@ private static RecordLayerInvokedRoutine.Builder generateInvokedRoutineBuilder(@ .withSerializableFunction(userDefinedScalarFunction); } - @Nonnull @SuppressWarnings("PMD.UnusedFormalParameter") // metadata will be used for view compilation in the future - private static RecordLayerView.Builder generateViewBuilder(@Nonnull final Supplier metadata, - @Nonnull final String name, - @Nonnull final String definition) { + private static RecordLayerView.Builder generateViewBuilder(final Supplier metadata, + final String name, + final String definition) { return RecordLayerView.newBuilder() .setName(name) .setDescription(definition) .setViewCompiler(getViewCompiler(name, metadata, definition)); } - @Nonnull public RecordMetaData getRecordMetaData() { return recordMetaData; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/RecordMetadataSerializer.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/RecordMetadataSerializer.java index abea5f55004..da1689a2276 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/RecordMetadataSerializer.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/RecordMetadataSerializer.java @@ -42,27 +42,25 @@ import com.google.protobuf.Descriptors; -import javax.annotation.Nonnull; @API(API.Status.EXPERIMENTAL) public class RecordMetadataSerializer extends SkeletonVisitor { - @Nonnull private final RecordMetaDataBuilder builder; private int recordTypeCounter; - public RecordMetadataSerializer(@Nonnull final Descriptors.FileDescriptor fileDescriptor) { + public RecordMetadataSerializer(final Descriptors.FileDescriptor fileDescriptor) { this(RecordMetaData.newBuilder().setRecords(fileDescriptor)); } - public RecordMetadataSerializer(@Nonnull final RecordMetaDataBuilder builder) { + public RecordMetadataSerializer(final RecordMetaDataBuilder builder) { this.builder = builder; this.recordTypeCounter = 0; } @Override - public void visit(@Nonnull Table table) { + public void visit(Table table) { Assert.thatUnchecked(table instanceof RecordLayerTable); final var recLayerTable = (RecordLayerTable) table; final KeyExpression keyExpression = recLayerTable.getPrimaryKey(); @@ -72,7 +70,7 @@ public void visit(@Nonnull Table table) { } @Override - public void visit(@Nonnull com.apple.foundationdb.relational.api.metadata.Index index) { + public void visit(com.apple.foundationdb.relational.api.metadata.Index index) { // Note: this does not preserve the index added and lest modified version, necessary // correctly handling index rebuilds when the template is updated. This also results // in the RecordMetaData builder updating its version, so the resulting meta-data will not @@ -89,7 +87,7 @@ public void visit(@Nonnull com.apple.foundationdb.relational.api.metadata.Index } @Override - public void visit(@Nonnull final InvokedRoutine invokedRoutine) { + public void visit(final InvokedRoutine invokedRoutine) { // do not serialize temporary routines in the record metadata. if (invokedRoutine.isTemporary()) { return; @@ -99,13 +97,13 @@ public void visit(@Nonnull final InvokedRoutine invokedRoutine) { } @Override - public void visit(@Nonnull final View view) { + public void visit(final View view) { Assert.thatUnchecked(view instanceof RecordLayerView); getBuilder().addView(((RecordLayerView)view).asRawView()); } @Override - public void visit(@Nonnull SchemaTemplate schemaTemplate) { + public void visit(SchemaTemplate schemaTemplate) { Assert.thatUnchecked(schemaTemplate instanceof RecordLayerSchemaTemplate); final var recLayerSchemaTemplate = (RecordLayerSchemaTemplate) schemaTemplate; getBuilder().setSplitLongRecords(schemaTemplate.isEnableLongRows()); @@ -117,7 +115,6 @@ public void visit(@Nonnull SchemaTemplate schemaTemplate) { } } - @Nonnull public RecordMetaDataBuilder getBuilder() { return builder; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/RoutineParser.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/RoutineParser.java index ba0ac594970..bf3e9365d33 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/RoutineParser.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/RoutineParser.java @@ -33,53 +33,46 @@ import com.apple.foundationdb.relational.recordlayer.query.visitors.BaseVisitor; import com.apple.foundationdb.relational.util.Assert; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.net.URI; import java.util.function.BiFunction; import java.util.function.Function; public interface RoutineParser { - @Nonnull - UserDefinedFunction parseFunction(@Nonnull String routineString, boolean isCaseSensitive); + UserDefinedFunction parseFunction(String routineString, boolean isCaseSensitive); - @Nonnull - LogicalOperator parseView(@Nonnull String viewName, @Nonnull String viewDefinition, boolean isCaseSensitive); + LogicalOperator parseView(String viewName, String viewDefinition, boolean isCaseSensitive); class DefaultSqlFunctionParser implements RoutineParser { - @Nonnull private final RecordLayerSchemaTemplate metaData; - private DefaultSqlFunctionParser(@Nonnull final RecordLayerSchemaTemplate metaData) { + private DefaultSqlFunctionParser(final RecordLayerSchemaTemplate metaData) { this.metaData = metaData; } - @Nonnull @Override - public CompiledSqlFunction parseFunction(@Nonnull final String routineString, boolean isCaseSensitive) { + public CompiledSqlFunction parseFunction(final String routineString, boolean isCaseSensitive) { return (CompiledSqlFunction)parse(routineString, null, PreparedParams.empty(), QueryParser::parseFunction, BaseVisitor::visitSqlInvokedFunction, isCaseSensitive); } - @Nonnull @Override - public LogicalOperator parseView(@Nonnull final String viewName, - @Nonnull final String viewDefinition, + public LogicalOperator parseView(final String viewName, + final String viewDefinition, boolean isCaseSensitive) { return parse(viewDefinition, viewName, PreparedParams.empty(), QueryParser::parseView, (v, p) -> v.getPlanGenerationContext().withDisabledLiteralProcessing(() -> Assert.castUnchecked(v.visit(p), LogicalOperator.class)), isCaseSensitive); } - @Nonnull @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - private T parse(@Nonnull final String query, + private T parse(final String query, @Nullable String scope, - @Nonnull final PreparedParams preparedParams, - @Nonnull final Function parse, - @Nonnull final BiFunction visit, + final PreparedParams preparedParams, + final Function parse, + final BiFunction visit, boolean isCaseSensitive) { final var parsed = parse.apply(query); final var planGenerationContext = new MutablePlanGenerationContext(preparedParams, @@ -93,8 +86,7 @@ private T parse(@Nonnull final String query, } } - @Nonnull - static DefaultSqlFunctionParser sqlFunctionParser(@Nonnull final RecordLayerSchemaTemplate metaData) { + static DefaultSqlFunctionParser sqlFunctionParser(final RecordLayerSchemaTemplate metaData) { return new DefaultSqlFunctionParser(metaData); } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/package-info.java index 5fdfb61aff1..e1641850fd5 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/package-info.java @@ -22,4 +22,7 @@ * Serialization and Deserialization APIs for Relational metadata. */ +@NullMarked package com.apple.foundationdb.relational.recordlayer.metadata.serde; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metric/StoreTimerMetricCollector.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metric/StoreTimerMetricCollector.java index 4c81479dc3c..00b8c1dc2b5 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metric/StoreTimerMetricCollector.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metric/StoreTimerMetricCollector.java @@ -32,8 +32,7 @@ import com.apple.foundationdb.relational.util.Supplier; import com.codahale.metrics.MetricRegistry; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.concurrent.TimeUnit; import java.util.function.Function; @@ -60,10 +59,9 @@ @API(API.Status.EXPERIMENTAL) public final class StoreTimerMetricCollector implements MetricCollector { - @Nonnull private final Function timerLookup; - private StoreTimerMetricCollector(@Nonnull final Function timerLookup) { + private StoreTimerMetricCollector(final Function timerLookup) { this.timerLookup = timerLookup; } @@ -75,8 +73,7 @@ private StoreTimerMetricCollector(@Nonnull final FunctionIf {@code context} has no timer attached (e.g. a transaction-bound database context), * the lookup returns {@code null} and the collector silently drops writes; reads throw.

*/ - @Nonnull - public static StoreTimerMetricCollector fromFDBRecordContext(@Nonnull final FDBRecordContext context) { + public static StoreTimerMetricCollector fromFDBRecordContext(final FDBRecordContext context) { return new StoreTimerMetricCollector(context::getTimerForEvent); } @@ -84,14 +81,13 @@ public static StoreTimerMetricCollector fromFDBRecordContext(@Nonnull final FDBR * Builds a fresh {@link MetricRegistryStoreTimer} over {@code registry} once, and hands it * back for every event lookup. All metrics land on the supplied Codahale registry. */ - @Nonnull - public static StoreTimerMetricCollector fromMetricRegistry(@Nonnull final MetricRegistry registry) { + public static StoreTimerMetricCollector fromMetricRegistry(final MetricRegistry registry) { final StoreTimer timer = new MetricRegistryStoreTimer(registry); return new StoreTimerMetricCollector(event -> timer); } @Override - public void increment(@Nonnull final RelationalMetric.RelationalCount count, final int val) { + public void increment(final RelationalMetric.RelationalCount count, final int val) { @Nullable final StoreTimer timer = timerLookup.apply(count); if (timer != null) { timer.increment(count, val); @@ -99,7 +95,7 @@ public void increment(@Nonnull final RelationalMetric.RelationalCount count, fin } @Override - public T clock(@Nonnull final RelationalMetric.RelationalEvent event, final Supplier supplier) throws RelationalException { + public T clock(final RelationalMetric.RelationalEvent event, final Supplier supplier) throws RelationalException { final long startNanos = System.nanoTime(); try { return supplier.get(); @@ -112,7 +108,7 @@ public T clock(@Nonnull final RelationalMetric.RelationalEvent event, final } @Override - public double getAverageTimeMicrosForEvent(@Nonnull final RelationalMetric.RelationalEvent event) { + public double getAverageTimeMicrosForEvent(final RelationalMetric.RelationalEvent event) { @Nullable final StoreTimer timer = timerLookup.apply(event); Assert.notNullUnchecked(timer, ErrorCode.INTERNAL_ERROR, "Cannot read metrics: no backing store timer for event %s", event.title()); @@ -126,7 +122,7 @@ public double getAverageTimeMicrosForEvent(@Nonnull final RelationalMetric.Relat } @Override - public long getCountsForCounter(@Nonnull final RelationalMetric.RelationalCount count) { + public long getCountsForCounter(final RelationalMetric.RelationalCount count) { @Nullable final StoreTimer timer = timerLookup.apply(count); Assert.notNullUnchecked(timer, ErrorCode.INTERNAL_ERROR, "Cannot read metrics: no backing store timer for count %s", count.title()); @@ -139,7 +135,7 @@ public long getCountsForCounter(@Nonnull final RelationalMetric.RelationalCount } @Override - public boolean hasCounter(@Nonnull final RelationalMetric.RelationalCount count) { + public boolean hasCounter(final RelationalMetric.RelationalCount count) { @Nullable final StoreTimer timer = timerLookup.apply(count); return timer != null && timer.getCounter(count) != null; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metric/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metric/package-info.java index 75330016049..c067ba4bf66 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metric/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metric/package-info.java @@ -22,4 +22,7 @@ * Metric artefacts in Relational backed by Record Layer APIs. */ +@NullMarked package com.apple.foundationdb.relational.recordlayer.metric; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/package-info.java index 57cda650ecd..e5c9f45c73b 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/package-info.java @@ -23,4 +23,7 @@ * * This implementation is directly embedded (so no rpc calls). */ +@NullMarked package com.apple.foundationdb.relational.recordlayer; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingLocatableResolverStore.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingLocatableResolverStore.java index 65bc5dd929c..449d97f34bb 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingLocatableResolverStore.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingLocatableResolverStore.java @@ -54,8 +54,7 @@ import com.google.protobuf.Descriptors; import com.google.protobuf.Message; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.Map; import java.util.NoSuchElementException; import java.util.concurrent.CompletableFuture; @@ -241,7 +240,6 @@ public RecordCursor scanIndex(Index index, TupleRange range, @Nullab throw new OperationUnsupportedException("Cannot scan indexes in interning layer store"); } - @Nonnull @Override public RecordMetaData getRecordMetaData() { return metaDataProvider.getRecordMetaData(); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingRecordStore.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingRecordStore.java index 7d83a3852f4..5f221ee6580 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingRecordStore.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingRecordStore.java @@ -62,8 +62,7 @@ import com.google.common.base.Throwables; import com.google.protobuf.Message; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.List; import java.util.Map; import java.util.Objects; @@ -211,18 +210,17 @@ public RecordCursor scanIndex(Index index, TupleRange range, @Nullab } } - @Nonnull @Override public RecordMetaData getRecordMetaData() { return recordStore.getRecordMetaData(); } - public static BackingRecordStore fromTransactionWithStore(@Nonnull RecordStoreAndRecordContextTransaction txn) { + public static BackingRecordStore fromTransactionWithStore(RecordStoreAndRecordContextTransaction txn) { return new BackingRecordStore(txn, txn.getRecordStore()); } @SuppressWarnings("PMD.PreserveStackTrace") - public static BackingRecordStore load(@Nonnull Transaction txn, @Nonnull StoreConfig config, @Nonnull FDBRecordStoreBase.StoreExistenceCheck existenceCheck) throws RelationalException { + public static BackingRecordStore load(Transaction txn, StoreConfig config, FDBRecordStoreBase.StoreExistenceCheck existenceCheck) throws RelationalException { //TODO(bfines) error handling if this store doesn't exist try { FDBRecordStore recordStore = FDBRecordStore.newBuilder() diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingStore.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingStore.java index 68f90e653cb..d647814312c 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingStore.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingStore.java @@ -35,7 +35,7 @@ import com.google.protobuf.Message; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.Map; public interface BackingStore extends RecordMetaDataProvider { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/LocatableResolverMetaDataProvider.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/LocatableResolverMetaDataProvider.java index 30c4e54633b..a2a87594918 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/LocatableResolverMetaDataProvider.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/LocatableResolverMetaDataProvider.java @@ -39,8 +39,7 @@ import com.google.protobuf.DynamicMessage; import com.google.protobuf.Message; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.List; final class LocatableResolverMetaDataProvider implements RecordMetaDataProvider { @@ -104,20 +103,17 @@ final class LocatableResolverMetaDataProvider implements RecordMetaDataProvider .build()) .build(); - @Nonnull private final RecordMetaData metaData; - @Nonnull private final Object interningTypeKey; - @Nonnull private final Object resolverStateTypeKey; - private LocatableResolverMetaDataProvider(@Nonnull RecordMetaData metaData) { + private LocatableResolverMetaDataProvider(RecordMetaData metaData) { this.metaData = metaData; interningTypeKey = metaData.getRecordType(INTERNING_TYPE_NAME).getRecordTypeKey(); resolverStateTypeKey = metaData.getRecordType(RESOLVER_STATE_TYPE_NAME).getRecordTypeKey(); } - Message wrapInterning(@Nonnull String key, long value, @Nullable byte[] metaData) { + Message wrapInterning(String key, long value, @Nullable byte[] metaData) { Descriptors.Descriptor descriptor = this.metaData.getRecordType(INTERNING_TYPE_NAME).getDescriptor(); DynamicMessage.Builder builder = DynamicMessage.newBuilder(descriptor) .setField(descriptor.findFieldByName(KEY_FIELD_NAME), key) @@ -129,14 +125,13 @@ Message wrapInterning(@Nonnull String key, long value, @Nullable byte[] metaData } @Nullable - Message wrapResolverResult(@Nonnull String key, @Nullable ResolverResult result) { + Message wrapResolverResult(String key, @Nullable ResolverResult result) { if (result == null) { return null; } return wrapInterning(key, result.getValue(), result.getMetadata()); } - @Nonnull Message wrapResolverState(ResolverStateProto.State state) { Descriptors.Descriptor descriptor = metaData.getRecordType(RESOLVER_STATE_TYPE_NAME).getDescriptor(); return DynamicMessage.newBuilder(descriptor) @@ -161,18 +156,15 @@ public static SchemaTemplate getSchemaTemplate() { return SCHEMA_TEMPLATE; } - @Nonnull @Override public RecordMetaData getRecordMetaData() { return metaData; } - @Nonnull public Object getInterningTypeKey() { return interningTypeKey; } - @Nonnull public Object getResolverStateTypeKey() { return resolverStateTypeKey; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/StoreConfig.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/StoreConfig.java index 291db2671a3..872c0b5b779 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/StoreConfig.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/StoreConfig.java @@ -43,8 +43,7 @@ import com.apple.foundationdb.relational.recordlayer.util.ExceptionUtil; import com.google.protobuf.Message; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.net.URI; import java.util.List; import java.util.zip.Deflater; @@ -126,8 +125,7 @@ public static StoreConfig create(RecordLayerConfig recordLayerConfig, return new StoreConfig(recordLayerConfig, schemaName, schemaPath, metaDataProvider, serializer); } - @Nonnull - static RecordSerializer serializerFromOptions(@Nonnull Options options) throws RelationalException { + static RecordSerializer serializerFromOptions(Options options) throws RelationalException { final boolean encrypted = options.getOption(Options.Name.ENCRYPT_WHEN_SERIALIZING); final boolean compressed = options.getOption(Options.Name.COMPRESS_WHEN_SERIALIZING); final SerializationKeyManager keyManager = keyManagerFromOptions(options); @@ -148,7 +146,7 @@ static RecordSerializer serializerFromOptions(@Nonnull Options options) } @Nullable - static SerializationKeyManager keyManagerFromOptions(@Nonnull Options options) throws RelationalException { + static SerializationKeyManager keyManagerFromOptions(Options options) throws RelationalException { final String keyStoreFileName = options.getOption(Options.Name.ENCRYPTION_KEY_STORE); if (keyStoreFileName == null) { return null; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/package-info.java index 328314b65d9..4909cb2836a 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/package-info.java @@ -24,4 +24,7 @@ * an interface that can then also be backed by other data structures, like a * {@link com.apple.foundationdb.record.provider.foundationdb.keyspace.LocatableResolver}. */ +@NullMarked package com.apple.foundationdb.relational.recordlayer.storage; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/expression/ExpressionFactoryImpl.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/expression/ExpressionFactoryImpl.java index b384332abd2..56bdd05322f 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/expression/ExpressionFactoryImpl.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/expression/ExpressionFactoryImpl.java @@ -35,7 +35,6 @@ import com.google.common.collect.ImmutableList; -import javax.annotation.Nonnull; import javax.annotation.concurrent.Immutable; import java.util.Optional; import java.util.stream.Collectors; @@ -45,20 +44,17 @@ @API(API.Status.EXPERIMENTAL) public class ExpressionFactoryImpl implements ExpressionFactory { - @Nonnull private final SchemaTemplate schemaTemplate; - @Nonnull private final Options options; - public ExpressionFactoryImpl(@Nonnull final SchemaTemplate schemaTemplate, - @Nonnull final Options options) { + public ExpressionFactoryImpl(final SchemaTemplate schemaTemplate, + final Options options) { this.schemaTemplate = schemaTemplate; this.options = options; } - @Nonnull - Field resolve(@Nonnull final DataType type, @Nonnull final Iterable fieldParts) { + Field resolve(final DataType type, final Iterable fieldParts) { final boolean caseSensitive = options.getOption(Options.Name.CASE_SENSITIVE_IDENTIFIERS); DataType current = type; final ImmutableList.Builder normalizedFieldParts = ImmutableList.builder(); @@ -85,9 +81,8 @@ Field resolve(@Nonnull final DataType type, @Nonnull final Iterable f return new FieldImpl<>(normalizedFieldParts.build(), this, current); } - @Nonnull @Override - public Field field(@Nonnull final String tableName, @Nonnull Iterable parts) { + public Field field(final String tableName, Iterable parts) { final boolean caseSensitive = options.getOption(Options.Name.CASE_SENSITIVE_IDENTIFIERS); final var normalizedName = Assert.notNullUnchecked(SemanticAnalyzer.normalizeString(tableName, caseSensitive)); final Optional
maybeTable; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/expression/FieldImpl.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/expression/FieldImpl.java index 92a24b73d1d..46a95fb033f 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/expression/FieldImpl.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/expression/FieldImpl.java @@ -30,51 +30,42 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.List; import java.util.Objects; @API(API.Status.EXPERIMENTAL) public class FieldImpl implements Field { - @Nonnull private final Iterable parts; - @Nonnull private final String name; - @Nonnull private final ExpressionFactoryImpl expressionFactory; - @Nonnull private final T dataType; - @Nonnull private final java.util.function.Supplier hashCodeSupplier = Suppliers.memoize(this::computeHashCode); - FieldImpl(@Nonnull final Iterable parts, - @Nonnull final ExpressionFactoryImpl expressionFactory, - @Nonnull final T dataType) { + FieldImpl(final Iterable parts, + final ExpressionFactoryImpl expressionFactory, + final T dataType) { this.name = Iterables.getLast(parts); this.parts = parts; this.expressionFactory = expressionFactory; this.dataType = dataType; } - @Nonnull @Override public Iterable getParts() { return parts; } - @Nonnull @Override - public Field subField(@Nonnull String part) { + public Field subField(String part) { return ((FieldImpl) expressionFactory.resolve(dataType, List.of(part))).withPrefix(parts); } - @Nonnull - private Field withPrefix(@Nonnull final Iterable prefix) { + private Field withPrefix(final Iterable prefix) { final ImmutableList.Builder builder = ImmutableList.builder(); builder.addAll(prefix).addAll(parts); return new FieldImpl<>(builder.build(), expressionFactory, dataType); @@ -82,11 +73,10 @@ private Field withPrefix(@Nonnull final Iterable prefix) { @Nullable @Override - public R accept(@Nonnull FluentVisitor visitor, @Nonnull C context) { + public R accept(FluentVisitor visitor, C context) { return visitor.visit(this, context); } - @Nonnull @Override public String getName() { return name; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/expression/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/expression/package-info.java index 34857ae42df..769e3f99107 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/expression/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/expression/package-info.java @@ -22,4 +22,7 @@ * Implementation of structured query expression API. */ +@NullMarked package com.apple.foundationdb.relational.recordlayer.structuredsql.expression; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/statement/StatementBuilderFactoryImpl.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/statement/StatementBuilderFactoryImpl.java index bf98baa79ae..4b6bc307e35 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/statement/StatementBuilderFactoryImpl.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/statement/StatementBuilderFactoryImpl.java @@ -30,53 +30,45 @@ import com.apple.foundationdb.relational.recordlayer.query.ParseTreeInfoImpl; import com.apple.foundationdb.relational.util.Assert; -import javax.annotation.Nonnull; import java.util.List; import java.util.Map; @API(API.Status.EXPERIMENTAL) public class StatementBuilderFactoryImpl implements StatementBuilderFactory { - @Nonnull private final SchemaTemplate schemaTemplate; - @Nonnull private final RelationalConnection relationalConnection; - public StatementBuilderFactoryImpl(@Nonnull SchemaTemplate schemaTemplate, @Nonnull RelationalConnection relationalConnection) { + public StatementBuilderFactoryImpl(SchemaTemplate schemaTemplate, RelationalConnection relationalConnection) { this.schemaTemplate = schemaTemplate; this.relationalConnection = relationalConnection; } - @Nonnull @Override public UpdateStatement.Builder updateStatementBuilder() { return new UpdateStatementImpl.BuilderImpl(relationalConnection, schemaTemplate); } - @Nonnull @Override - public UpdateStatement.Builder updateStatementBuilder(@Nonnull final String updateQuery) { + public UpdateStatement.Builder updateStatementBuilder(final String updateQuery) { return UpdateStatementImpl.BuilderImpl.fromQuery(relationalConnection, schemaTemplate, updateQuery, Map.of()); } - @Nonnull @Override - public UpdateStatement.Builder updateStatementBuilder(@Nonnull String updateQuery, @Nonnull Map> columnSynonyms) { + public UpdateStatement.Builder updateStatementBuilder(String updateQuery, Map> columnSynonyms) { return UpdateStatementImpl.BuilderImpl.fromQuery(relationalConnection, schemaTemplate, updateQuery, columnSynonyms); } - @Nonnull @Override - public UpdateStatement.Builder updateStatementBuilder(@Nonnull final ParseTreeInfo parseTree) { + public UpdateStatement.Builder updateStatementBuilder(final ParseTreeInfo parseTree) { Assert.thatUnchecked(parseTree instanceof ParseTreeInfoImpl); return UpdateStatementImpl.BuilderImpl.fromParseTreeInfoImpl(relationalConnection, schemaTemplate, (ParseTreeInfoImpl) parseTree, Map.of()); } - @Nonnull @Override - public UpdateStatement.Builder updateStatementBuilder(@Nonnull final ParseTreeInfo parseTree, - @Nonnull final Map> columnSynonyms) { + public UpdateStatement.Builder updateStatementBuilder(final ParseTreeInfo parseTree, + final Map> columnSynonyms) { Assert.thatUnchecked(parseTree instanceof ParseTreeInfoImpl); return UpdateStatementImpl.BuilderImpl.fromParseTreeInfoImpl(relationalConnection, schemaTemplate, (ParseTreeInfoImpl) parseTree, columnSynonyms); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/statement/UpdateStatementImpl.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/statement/UpdateStatementImpl.java index 57507d970cf..425b84051dc 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/statement/UpdateStatementImpl.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/statement/UpdateStatementImpl.java @@ -56,8 +56,7 @@ import org.antlr.v4.runtime.tree.TerminalNode; import org.antlr.v4.runtime.tree.TerminalNodeImpl; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.ArrayList; @@ -75,40 +74,33 @@ @API(API.Status.EXPERIMENTAL) public class UpdateStatementImpl implements UpdateStatement { - @Nonnull private final Table table; - @Nonnull private final String originalTableName; - @Nonnull private final Map, Expression> setClauses; @Nullable private final BooleanExpressionTrait whereClause; - @Nonnull private final List> returning; - @Nonnull private final Set queryOptions; - @Nonnull private final Supplier sqlGenerationMemoizer; - @Nonnull private final RelationalConnection connection; private final boolean caseSensitive; @SuppressWarnings("this-escape") - public UpdateStatementImpl(@Nonnull Table table, - @Nonnull final String originalTableName, - @Nonnull Map, Expression> setClauses, + public UpdateStatementImpl(Table table, + final String originalTableName, + Map, Expression> setClauses, @Nullable BooleanExpressionTrait whereClause, - @Nonnull List> returning, - @Nonnull Set queryOptions, - @Nonnull RelationalConnection connection) { + List> returning, + Set queryOptions, + RelationalConnection connection) { this.table = table; this.originalTableName = originalTableName; this.setClauses = ImmutableMap.copyOf(setClauses); @@ -120,25 +112,21 @@ public UpdateStatementImpl(@Nonnull Table table, this.caseSensitive = connection.getOptions().getOption(Options.Name.CASE_SENSITIVE_IDENTIFIERS); } - @Nonnull @Override public PreparedStatement getPreparedStatement() throws SQLException { return connection.prepareStatement(getSqlQuery()); } - @Nonnull @Override public String getSqlQuery() { return sqlGenerationMemoizer.get(); } - @Nonnull @Override public Map, Expression> getSetClauses() { return ImmutableMap.copyOf(setClauses); } - @Nonnull @Override public List> getReturning() { return ImmutableList.copyOf(returning); @@ -150,19 +138,16 @@ public BooleanExpressionTrait getWhereClause() { return whereClause; } - @Nonnull @Override public Set getOptions() { return ImmutableSet.copyOf(queryOptions); } - @Nonnull @Override public String getTable() { return table.getName(); } - @Nonnull private String generateQuery() { final var sb = new StringBuilder(); final var sqlVisitor = new SqlVisitor(); @@ -201,32 +186,27 @@ private String generateQuery() { public static class BuilderImpl implements UpdateStatement.Builder { - @Nonnull private final RelationalConnection connection; - @Nonnull private final SchemaTemplate schemaTemplate; private Table table; private String originalTableName; - @Nonnull private Map, Expression> setClauses; @Nullable private BooleanExpressionTrait whereClause; - @Nonnull private final List> returning; - @Nonnull private final ImmutableSet.Builder queryOptionsBuilder; private final boolean isCaseSensitive; - public BuilderImpl(@Nonnull final RelationalConnection connection, - @Nonnull final SchemaTemplate schemaTemplate) { + public BuilderImpl(final RelationalConnection connection, + final SchemaTemplate schemaTemplate) { this.connection = connection; this.schemaTemplate = schemaTemplate; this.setClauses = new LinkedHashMap<>(); @@ -235,47 +215,40 @@ public BuilderImpl(@Nonnull final RelationalConnection connection, this.isCaseSensitive = connection.getOptions().getOption(Options.Name.CASE_SENSITIVE_IDENTIFIERS); } - @Nonnull @Override public Map, Expression> getSetClauses() { return setClauses; } - @Nonnull @Override - public Builder addSetClause(@Nonnull Field field, @Nonnull Expression newValue) { + public Builder addSetClause(Field field, Expression newValue) { setClauses.put(field, newValue); return this; } - @Nonnull @Override public Builder clearSetClauses() { this.setClauses.clear(); return this; } - @Nonnull @Override - public Builder removeSetClause(@Nonnull Field field) { + public Builder removeSetClause(Field field) { setClauses = setClauses.entrySet().stream().filter(pair -> !pair.getKey().equals(field)).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); return this; } - @Nonnull @Override public List> getReturning() { return returning; } - @Nonnull @Override - public Builder addReturning(@Nonnull Expression expression) { + public Builder addReturning(Expression expression) { this.returning.add(expression); return this; } - @Nonnull @Override public Builder clearReturning() { this.returning.clear(); @@ -288,9 +261,8 @@ public BooleanExpressionTrait getWhereClause() { return whereClause; } - @Nonnull @Override - public Builder addWhereClause(@Nonnull BooleanExpressionTrait expression) { + public Builder addWhereClause(BooleanExpressionTrait expression) { if (whereClause != null) { whereClause = whereClause.and(expression); } else { @@ -299,22 +271,19 @@ public Builder addWhereClause(@Nonnull BooleanExpressionTrait expression) { return this; } - @Nonnull @Override public Builder clearWhereClause() { this.whereClause = null; return this; } - @Nonnull @Override public String getTable() { return originalTableName; } - @Nonnull @Override - public Builder setTable(@Nonnull final String table) { + public Builder setTable(final String table) { final var normalizedTableName = Assert.notNullUnchecked(SemanticAnalyzer.normalizeString(table, isCaseSensitive)); Optional
maybeTable; @@ -330,9 +299,8 @@ public Builder setTable(@Nonnull final String table) { return this; } - @Nonnull @Override - public Builder resolveSetFields(@Nonnull final ExpressionFactory expressionFactory) { + public Builder resolveSetFields(final ExpressionFactory expressionFactory) { if (setClauses.entrySet().stream().allMatch(entry -> entry.getKey() instanceof FieldImpl)) { return this; } @@ -348,20 +316,17 @@ public Builder resolveSetFields(@Nonnull final ExpressionFactory expressionFacto return this; } - @Nonnull @Override - public Builder withOption(@Nonnull final QueryOptions... options) { + public Builder withOption(final QueryOptions... options) { Arrays.stream(options).forEach(queryOptionsBuilder::add); return this; } - @Nonnull @Override public Set getOptions() { return queryOptionsBuilder.build(); } - @Nonnull @Override public UpdateStatement build() throws RelationalException { Assert.notNull(table, ErrorCode.UNDEFINED_TABLE, "table is not set"); @@ -371,28 +336,25 @@ public UpdateStatement build() throws RelationalException { @SuppressWarnings("PMD.FormalParameterNamingConventions") private static final class UpdateVisitor extends RelationalParserBaseVisitor { - @Nonnull @SuppressWarnings("PMD.AvoidStringBufferField") // the visitor is used within the builder, it should be very short-lived. private final StringBuilder queryStringScratchpad; - @Nonnull private final Builder updateBuilder; - @Nonnull private final ExpressionFactory expressionFactory; private boolean isUpdateStatement; - public UpdateVisitor(@Nonnull final RelationalConnection connection, - @Nonnull final SchemaTemplate schemaTemplate, - @Nonnull final ParseTree ast) { + public UpdateVisitor(final RelationalConnection connection, + final SchemaTemplate schemaTemplate, + final ParseTree ast) { this(connection, schemaTemplate, ast, Map.of()); } - public UpdateVisitor(@Nonnull final RelationalConnection connection, - @Nonnull final SchemaTemplate schemaTemplate, - @Nonnull final ParseTree ast, - @Nonnull final Map> columnSynonyms) { + public UpdateVisitor(final RelationalConnection connection, + final SchemaTemplate schemaTemplate, + final ParseTree ast, + final Map> columnSynonyms) { this.queryStringScratchpad = new StringBuilder(); this.updateBuilder = new BuilderImpl(connection, schemaTemplate); try { @@ -412,13 +374,11 @@ public UpdateVisitor(@Nonnull final RelationalConnection connection, } } - @Nonnull Builder getUpdateBuilder() { return updateBuilder; } - @Nonnull - private String withNewScratchPad(@Nonnull final Consumer consumer) { + private String withNewScratchPad(final Consumer consumer) { queryStringScratchpad.setLength(0); consumer.accept(null); return queryStringScratchpad.toString().trim(); @@ -472,13 +432,11 @@ public Void visitStatementOption(RelationalParser.StatementOptionContext ctx) { return null; } - @Nonnull private List handleFullId(RelationalParser.FullIdContext ctx) { Assert.thatUnchecked(!ctx.uid().isEmpty()); return ctx.uid().stream().map(this::handleUid).map(Assert::notNullUnchecked).collect(Collectors.toList()); } - @Nonnull private String handleUid(RelationalParser.UidContext ctx) { if (ctx.simpleId() != null) { return Assert.notNullUnchecked(ctx.simpleId().getText()); @@ -487,7 +445,6 @@ private String handleUid(RelationalParser.UidContext ctx) { } } - @Nonnull private List handleReturningSelectElements(RelationalParser.SelectElementsContext selectElementsContext) { final ImmutableList.Builder result = ImmutableList.builder(); selectElementsContext.selectElement().forEach(selectElement -> result.add(withNewScratchPad(Null -> visit(selectElement)))); @@ -506,7 +463,7 @@ public Void visitTerminal(TerminalNode node) { public static final class CustomSimpleId extends RelationalParser.UidContext { - public CustomSimpleId(ParserRuleContext parent, int invokingState, @Nonnull final String name) { + public CustomSimpleId(ParserRuleContext parent, int invokingState, final String name) { super(parent, invokingState); addChild(new TerminalNodeImpl(new CustomCommonToken(name))); } @@ -515,10 +472,9 @@ public static class CustomCommonToken extends CommonToken { private static final long serialVersionUID = 3459762348795L; - @Nonnull private final String name; - public CustomCommonToken(@Nonnull final String name) { + public CustomCommonToken(final String name) { super(0); // maybe use something else. this.name = name; } @@ -532,12 +488,11 @@ public String getText() { private static final class UidReplacer extends RelationalParserBaseVisitor { - @Nonnull private final ImmutableMap> synonymsMap; private final boolean isCaseSensitive; - private UidReplacer(@Nonnull final Map> symnonymsMap, boolean isCaseSensitive) { + private UidReplacer(final Map> symnonymsMap, boolean isCaseSensitive) { ImmutableMap.Builder> normalizedSynonymsMap = ImmutableMap.builder(); for (final var synonymsPair : symnonymsMap.entrySet()) { final var normalizedKey = Assert.notNullUnchecked(SemanticAnalyzer.normalizeString(synonymsPair.getKey(), isCaseSensitive)); @@ -583,21 +538,19 @@ public Void visitUid(RelationalParser.UidContext ctx) { } } - @Nonnull - public static Builder fromQuery(@Nonnull final RelationalConnection relationalConnection, - @Nonnull final SchemaTemplate schemaTemplate, - @Nonnull final String updateQuery, - @Nonnull final Map> columnSynonyms) { + public static Builder fromQuery(final RelationalConnection relationalConnection, + final SchemaTemplate schemaTemplate, + final String updateQuery, + final Map> columnSynonyms) { final var tokenSource = new RelationalLexer(new CaseInsensitiveCharStream(updateQuery)); final var parseTree = new RelationalParser(new CommonTokenStream(tokenSource)); return fromParseTreeInfoImpl(relationalConnection, schemaTemplate, ParseTreeInfoImpl.from(parseTree.root()), columnSynonyms); } - @Nonnull - public static Builder fromParseTreeInfoImpl(@Nonnull final RelationalConnection relationalConnection, - @Nonnull final SchemaTemplate schemaTemplate, - @Nonnull final ParseTreeInfoImpl parseTreeInfo, - @Nonnull final Map> columnSynonyms) { + public static Builder fromParseTreeInfoImpl(final RelationalConnection relationalConnection, + final SchemaTemplate schemaTemplate, + final ParseTreeInfoImpl parseTreeInfo, + final Map> columnSynonyms) { Assert.thatUnchecked(parseTreeInfo.getQueryType().equals(ParseTreeInfo.QueryType.UPDATE), String.format(Locale.ROOT, "Expecting update statement, got '%s' statement", parseTreeInfo.getQueryType().name())); final var updateVisitor = new UpdateVisitor(relationalConnection, schemaTemplate, parseTreeInfo.getRootContext(), columnSynonyms); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/statement/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/statement/package-info.java index 7f95ef7631c..45bbeb8af2a 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/statement/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/statement/package-info.java @@ -22,4 +22,7 @@ * Implementation of structured query statement API. */ +@NullMarked package com.apple.foundationdb.relational.recordlayer.structuredsql.statement; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/ExceptionUtil.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/ExceptionUtil.java index 4ffe82f4a9b..5180705e0f1 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/ExceptionUtil.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/ExceptionUtil.java @@ -35,7 +35,6 @@ import com.apple.foundationdb.relational.api.exceptions.UncheckedRelationalException; import com.google.common.base.VerifyException; -import javax.annotation.Nonnull; import java.sql.SQLException; import java.util.Map; @@ -84,8 +83,7 @@ private static RelationalException recordCoreToRelationalException(RecordCoreExc return new RelationalException(code, re).withContext(extraContext); } - @Nonnull - private static ErrorCode translateErrorCode(@Nonnull final SemanticException semanticException) { + private static ErrorCode translateErrorCode(final SemanticException semanticException) { final var semanticErrorCode = semanticException.getErrorCode(); switch (semanticErrorCode) { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/Hex.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/Hex.java index e1950a1aa31..ee8b14fff81 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/Hex.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/Hex.java @@ -25,7 +25,7 @@ import com.apple.foundationdb.relational.api.exceptions.ErrorCode; import com.apple.foundationdb.relational.api.exceptions.RelationalException; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/MemoizedFunction.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/MemoizedFunction.java index ec6e75d7659..b418d95f51f 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/MemoizedFunction.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/MemoizedFunction.java @@ -22,7 +22,6 @@ import com.google.common.base.Function; -import javax.annotation.Nonnull; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -34,14 +33,13 @@ */ public class MemoizedFunction { - @Nonnull private final Map cache; private MemoizedFunction() { cache = new ConcurrentHashMap<>(); } - private Function wrap(@Nonnull final Function function) { + private Function wrap(final Function function) { return input -> cache.computeIfAbsent(input, function); } @@ -52,7 +50,7 @@ private Function wrap(@Nonnull final Function function) { * @param The type of the function codomain. * @return A memoized version of the provided function. */ - public static Function memoize(@Nonnull final Function function) { + public static Function memoize(final Function function) { return new MemoizedFunction().wrap(function); } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/MetricRegistryStoreTimer.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/MetricRegistryStoreTimer.java index 7553eccc0ce..5a3a05204ff 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/MetricRegistryStoreTimer.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/MetricRegistryStoreTimer.java @@ -28,8 +28,7 @@ import com.codahale.metrics.MetricFilter; import com.codahale.metrics.MetricRegistry; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.concurrent.TimeUnit; /** @@ -52,7 +51,7 @@ public MetricRegistryStoreTimer(MetricRegistry registry) { @Nullable @Override - protected Counter getCounter(@Nonnull Event event, boolean createIfNotExists) { + protected Counter getCounter(Event event, boolean createIfNotExists) { if (event instanceof Aggregate) { @Nullable Counter counter = ((Aggregate) event).compute(this); if (counter == null && createIfNotExists) { @@ -77,7 +76,7 @@ protected Counter getCounter(@Nonnull Event event, boolean createIfNotExists) { @Nullable @Override - protected Counter getTimeoutCounter(@Nonnull Event event, boolean createIfNotExists) { + protected Counter getTimeoutCounter(Event event, boolean createIfNotExists) { if (event instanceof Count) { return MapUtils.computeIfAbsent(counters, event, evignore -> new RegistryCounter(event.title(), registry.counter(event.title()))); @@ -97,7 +96,7 @@ private static class RegistryCounter extends Counter { private final com.codahale.metrics.Counter counter; private final String name; - public RegistryCounter(@Nonnull String name, com.codahale.metrics.Counter counter) { + public RegistryCounter(String name, com.codahale.metrics.Counter counter) { super(false); this.name = name; this.counter = counter; @@ -121,7 +120,7 @@ private static class RegistryTimer extends Counter { private final String name; - public RegistryTimer(@Nonnull String name, com.codahale.metrics.Timer timer) { + public RegistryTimer(String name, com.codahale.metrics.Timer timer) { super(false); this.name = name; this.timer = timer; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/TypeUtils.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/TypeUtils.java index 15fb1643258..7e904e5c8c2 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/TypeUtils.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/TypeUtils.java @@ -28,24 +28,21 @@ import com.apple.foundationdb.relational.util.Assert; import com.google.common.collect.ImmutableList; -import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.Comparator; import java.util.Optional; public final class TypeUtils { - @Nonnull - public static Type setFieldNames(@Nonnull final Type input, - @Nonnull final CompatibleTypeEvolutionPredicate.FieldAccessTrieNode fieldAccessTrieNode) { + public static Type setFieldNames(final Type input, + final CompatibleTypeEvolutionPredicate.FieldAccessTrieNode fieldAccessTrieNode) { return setFieldNamesInternal(input, fieldAccessTrieNode); } - @Nonnull // PMD incorrectly thinks that comparing array sizes it deemed to be object reference comparison requiring equals() instead. @SuppressWarnings("PMD.CompareObjectsWithEquals") - private static Type setFieldNamesInternal(@Nonnull final Type input, - @Nonnull final CompatibleTypeEvolutionPredicate.FieldAccessTrieNode trie) { + private static Type setFieldNamesInternal(final Type input, + final CompatibleTypeEvolutionPredicate.FieldAccessTrieNode trie) { if (input.isPrimitive()) { return input; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/package-info.java index 06a5a3523b3..b71650efb27 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/package-info.java @@ -21,4 +21,7 @@ /** * Contains a set of utility methods. */ +@NullMarked package com.apple.foundationdb.relational.recordlayer.util; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/TransactionBoundEmbeddedRelationalEngine.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/TransactionBoundEmbeddedRelationalEngine.java index a916db6a0c9..e30408eb06d 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/TransactionBoundEmbeddedRelationalEngine.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/TransactionBoundEmbeddedRelationalEngine.java @@ -28,8 +28,7 @@ import com.apple.foundationdb.relational.api.metrics.NoOpMetricRegistry; import com.apple.foundationdb.relational.recordlayer.query.cache.RelationalPlanCache; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.Collection; import java.util.List; @@ -46,11 +45,11 @@ public TransactionBoundEmbeddedRelationalEngine() { this(Options.NONE); } - public TransactionBoundEmbeddedRelationalEngine(@Nonnull Options engineOptions) { + public TransactionBoundEmbeddedRelationalEngine(Options engineOptions) { this(engineOptions, null); } - public TransactionBoundEmbeddedRelationalEngine(@Nonnull Options engineOptions, + public TransactionBoundEmbeddedRelationalEngine(Options engineOptions, @Nullable KeySpace keySpace) { super(List.of(new TransactionBoundStorageCluster(null, keySpace)), NoOpMetricRegistry.INSTANCE); final Integer primaryCacheSize = engineOptions.getOption(Options.Name.PLAN_CACHE_PRIMARY_MAX_ENTRIES); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/TransactionBoundStorageCluster.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/TransactionBoundStorageCluster.java index 58d8af69f7a..01cabfb98b5 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/TransactionBoundStorageCluster.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/TransactionBoundStorageCluster.java @@ -30,8 +30,7 @@ import com.apple.foundationdb.relational.recordlayer.catalog.TransactionBoundDatabase; import com.apple.foundationdb.relational.recordlayer.query.cache.RelationalPlanCache; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.net.URI; /** @@ -53,7 +52,7 @@ public TransactionBoundStorageCluster(@Nullable RelationalPlanCache planCache, @Nullable @Override - public RelationalDatabase loadDatabase(@Nonnull URI url, @Nonnull Options connOptions) { + public RelationalDatabase loadDatabase(URI url, Options connOptions) { return new TransactionBoundDatabase(url, connOptions, planCache, keySpace); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/catalog/HollowSchemaTemplateCatalog.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/catalog/HollowSchemaTemplateCatalog.java index df722529cdc..5ad9bbb87ad 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/catalog/HollowSchemaTemplateCatalog.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/catalog/HollowSchemaTemplateCatalog.java @@ -28,7 +28,6 @@ import com.apple.foundationdb.relational.api.exceptions.RelationalException; import com.apple.foundationdb.relational.api.metadata.SchemaTemplate; -import javax.annotation.Nonnull; @API(API.Status.EXPERIMENTAL) public class HollowSchemaTemplateCatalog implements SchemaTemplateCatalog { @@ -36,44 +35,42 @@ public class HollowSchemaTemplateCatalog implements SchemaTemplateCatalog { public static final HollowSchemaTemplateCatalog INSTANCE = new HollowSchemaTemplateCatalog(); @Override - public boolean doesSchemaTemplateExist(@Nonnull Transaction txn, @Nonnull String templateName) throws RelationalException { + public boolean doesSchemaTemplateExist(Transaction txn, String templateName) throws RelationalException { throw new OperationUnsupportedException("This Schema Template Catalog is hollow and does not support calls."); } @Override - public boolean doesSchemaTemplateExist(@Nonnull Transaction txn, @Nonnull String templateName, int version) throws RelationalException { + public boolean doesSchemaTemplateExist(Transaction txn, String templateName, int version) throws RelationalException { throw new OperationUnsupportedException("This Schema Template Catalog is hollow and does not support calls."); } - @Nonnull @Override - public SchemaTemplate loadSchemaTemplate(@Nonnull Transaction txn, @Nonnull String templateName) throws RelationalException { + public SchemaTemplate loadSchemaTemplate(Transaction txn, String templateName) throws RelationalException { throw new OperationUnsupportedException("This Schema Template Catalog is hollow and does not support calls."); } - @Nonnull @Override - public SchemaTemplate loadSchemaTemplate(@Nonnull Transaction txn, @Nonnull String templateId, int version) throws RelationalException { + public SchemaTemplate loadSchemaTemplate(Transaction txn, String templateId, int version) throws RelationalException { throw new OperationUnsupportedException("This Schema Template Catalog is hollow and does not support calls."); } @Override - public void createTemplate(@Nonnull Transaction txn, @Nonnull SchemaTemplate newTemplate) throws RelationalException { + public void createTemplate(Transaction txn, SchemaTemplate newTemplate) throws RelationalException { throw new OperationUnsupportedException("This Schema Template Catalog is hollow and does not support calls."); } @Override - public RelationalResultSet listTemplates(@Nonnull Transaction txn) { + public RelationalResultSet listTemplates(Transaction txn) { throw new OperationUnsupportedException("This Schema Template Catalog is hollow and does not support calls.").toUncheckedWrappedException(); } @Override - public void deleteTemplate(@Nonnull Transaction txn, @Nonnull String templateId, boolean throwIfDoesNotExist) { + public void deleteTemplate(Transaction txn, String templateId, boolean throwIfDoesNotExist) { throw new OperationUnsupportedException("This Schema Template Catalog is hollow and does not support calls.").toUncheckedWrappedException(); } @Override - public void deleteTemplate(@Nonnull Transaction txn, @Nonnull String templateId, int version, boolean throwIfDoesNotExist) throws RelationalException { + public void deleteTemplate(Transaction txn, String templateId, int version, boolean throwIfDoesNotExist) throws RelationalException { throw new OperationUnsupportedException("This Schema Template Catalog is hollow and does not support calls."); } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/catalog/HollowStoreCatalog.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/catalog/HollowStoreCatalog.java index 5c0423b4fc7..89db0d9fa07 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/catalog/HollowStoreCatalog.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/catalog/HollowStoreCatalog.java @@ -34,19 +34,17 @@ import com.apple.foundationdb.relational.api.metadata.SchemaTemplate; import com.apple.foundationdb.relational.util.catalog.KeySpaceProvider; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.net.URI; @API(API.Status.EXPERIMENTAL) public class HollowStoreCatalog implements StoreCatalog, KeySpaceProvider { - @Nonnull public final SchemaTemplate schemaTemplate; @Nullable private final KeySpace keySpace; - public HollowStoreCatalog(@Nonnull final SchemaTemplate schemaTemplate, @Nullable final KeySpace keySpace) { + public HollowStoreCatalog(final SchemaTemplate schemaTemplate, @Nullable final KeySpace keySpace) { this.schemaTemplate = schemaTemplate; this.keySpace = keySpace; } @@ -56,62 +54,61 @@ public SchemaTemplateCatalog getSchemaTemplateCatalog() { return null; } - @Nonnull @Override - public Schema loadSchema(@Nonnull Transaction txn, @Nonnull URI databaseId, @Nonnull String schemaName) throws RelationalException { + public Schema loadSchema(Transaction txn, URI databaseId, String schemaName) throws RelationalException { return schemaTemplate.generateSchema(databaseId.toString(), schemaName); } @Override - public void saveSchema(@Nonnull Transaction txn, @Nonnull Schema dataToWrite, boolean createDatabaseIfNecessary, - @Nonnull SchemaExistsBehavior existsBehavior) throws RelationalException { + public void saveSchema(Transaction txn, Schema dataToWrite, boolean createDatabaseIfNecessary, + SchemaExistsBehavior existsBehavior) throws RelationalException { throw new OperationUnsupportedException("This store catalog is hollow and does not support calls."); } @Override - public void repairSchema(@Nonnull Transaction txn, @Nonnull String databaseId, @Nonnull String schemaName) throws RelationalException { + public void repairSchema(Transaction txn, String databaseId, String schemaName) throws RelationalException { throw new OperationUnsupportedException("This store catalog is hollow and does not support calls."); } @Override - public void createDatabase(@Nonnull Transaction txn, @Nonnull URI dbUri) throws RelationalException { + public void createDatabase(Transaction txn, URI dbUri) throws RelationalException { throw new OperationUnsupportedException("This store catalog is hollow and does not support calls."); } @Override - public RelationalResultSet listDatabases(@Nonnull Transaction txn, @Nonnull Continuation continuation) throws RelationalException { + public RelationalResultSet listDatabases(Transaction txn, Continuation continuation) throws RelationalException { throw new OperationUnsupportedException("This store catalog is hollow and does not support calls."); } @Override - public RelationalResultSet listSchemas(@Nonnull Transaction txn, @Nonnull Continuation continuation) throws RelationalException { + public RelationalResultSet listSchemas(Transaction txn, Continuation continuation) throws RelationalException { throw new OperationUnsupportedException("This store catalog is hollow and does not support calls."); } @Override - public RelationalResultSet listSchemas(@Nonnull Transaction txn, @Nonnull URI databaseId, @Nonnull Continuation continuation) throws RelationalException { + public RelationalResultSet listSchemas(Transaction txn, URI databaseId, Continuation continuation) throws RelationalException { throw new OperationUnsupportedException("This store catalog is hollow and does not support calls."); } @Override - public void deleteSchema(@Nonnull Transaction txn, @Nonnull URI dbUri, @Nonnull String schemaName) throws RelationalException { + public void deleteSchema(Transaction txn, URI dbUri, String schemaName) throws RelationalException { throw new OperationUnsupportedException("This store catalog is hollow and does not support calls."); } @Override - public boolean doesDatabaseExist(@Nonnull Transaction txn, @Nonnull URI dbUrl) throws RelationalException { + public boolean doesDatabaseExist(Transaction txn, URI dbUrl) throws RelationalException { throw new OperationUnsupportedException("This store catalog is hollow and does not support calls."); } @Override - public boolean doesSchemaExist(@Nonnull Transaction txn, @Nonnull URI dbUri, @Nonnull String schemaName) { + public boolean doesSchemaExist(Transaction txn, URI dbUri, String schemaName) { // We do not check schema existence in this hollow catalog as it should be checked by the caller return true; } @Override - public boolean deleteDatabase(@Nonnull Transaction txn, @Nonnull URI dbUrl, boolean throwIfDoesNotExist) throws RelationalException { + public boolean deleteDatabase(Transaction txn, URI dbUrl, boolean throwIfDoesNotExist) throws RelationalException { throw new OperationUnsupportedException("This store catalog is hollow and does not support calls."); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/catalog/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/catalog/package-info.java index 1a0309c0989..d5b3ca9b708 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/catalog/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/catalog/package-info.java @@ -22,4 +22,7 @@ * A collection of testing systems which are based on comparing results to equivalent queries in an embedded * SQL database. */ -package com.apple.foundationdb.relational.compare; +@NullMarked +package com.apple.foundationdb.relational.transactionbound.catalog; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/package-info.java index 9263c2f0223..e65b779f0ae 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/package-info.java @@ -22,4 +22,7 @@ * A collection of testing systems which are based on comparing results to equivalent queries in an embedded * SQL database. */ +@NullMarked package com.apple.foundationdb.relational.transactionbound; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/AbstractRecordLayerResultSetTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/AbstractRecordLayerResultSetTest.java index affdbb77e58..8b141ff5c51 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/AbstractRecordLayerResultSetTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/AbstractRecordLayerResultSetTest.java @@ -37,7 +37,6 @@ import org.junit.jupiter.params.provider.MethodSource; import org.mockito.Mockito; -import javax.annotation.Nonnull; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.SQLException; @@ -185,7 +184,6 @@ protected Row advanceRow() { } @Override - @Nonnull public Continuation getContinuation() { return ContinuationImpl.BEGIN; } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/AutoCommitTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/AutoCommitTests.java index f3ab88316d9..26e136ad5ff 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/AutoCommitTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/AutoCommitTests.java @@ -41,7 +41,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; -import javax.annotation.Nonnull; import java.net.URI; import java.sql.SQLException; import java.util.List; @@ -656,7 +655,7 @@ public void newTransactionForEachExecutionOfStatement() throws SQLException, Rel } } - private static void checkOpenTransaction(@Nonnull EmbeddedRelationalConnection connection, TransactionType transactionType) { + private static void checkOpenTransaction(EmbeddedRelationalConnection connection, TransactionType transactionType) { if (transactionType == TransactionType.AUTO_COMMIT_ON) { Assertions.assertFalse(connection.inActiveTransaction()); } else { @@ -664,7 +663,7 @@ private static void checkOpenTransaction(@Nonnull EmbeddedRelationalConnection c } } - private static void checkAutoCommitAndCommitIfRequired(@Nonnull EmbeddedRelationalConnection connection, TransactionType transactionType) throws SQLException { + private static void checkAutoCommitAndCommitIfRequired(EmbeddedRelationalConnection connection, TransactionType transactionType) throws SQLException { if (transactionType == TransactionType.AUTO_COMMIT_ON || transactionType == TransactionType.EXISTING_TRANSACTION) { Assertions.assertTrue(connection.getAutoCommit()); } else { @@ -675,7 +674,7 @@ private static void checkAutoCommitAndCommitIfRequired(@Nonnull EmbeddedRelation } } - private static void setAutoCommit(@Nonnull RelationalConnection connection, TransactionType transactionType) throws SQLException { + private static void setAutoCommit(RelationalConnection connection, TransactionType transactionType) throws SQLException { if (transactionType == TransactionType.AUTO_COMMIT_ON) { connection.setAutoCommit(true); } else if (transactionType == TransactionType.AUTO_COMMIT_OFF_WITH_EXPLICIT_COMMIT || transactionType == TransactionType.AUTO_COMMIT_OFF_WITH_NO_COMMIT) { @@ -683,7 +682,7 @@ private static void setAutoCommit(@Nonnull RelationalConnection connection, Tran } } - private static EmbeddedRelationalConnection getConnectionWithExistingTransaction(@Nonnull EmbeddedRelationalConnection connection, @Nonnull URI uri, @Nonnull EmbeddedRelationalDriver alternateDriver) throws SQLException, RelationalException { + private static EmbeddedRelationalConnection getConnectionWithExistingTransaction(EmbeddedRelationalConnection connection, URI uri, EmbeddedRelationalDriver alternateDriver) throws SQLException, RelationalException { final var store = TransactionBoundDatabaseTest.getStore(connection); final var schemaTemplate = TransactionBoundDatabaseTest.getSchemaTemplate(connection); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CaseSensitiveDbObjectsTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CaseSensitiveDbObjectsTest.java index 62c50f5fbe0..3eead9ec2cb 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CaseSensitiveDbObjectsTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CaseSensitiveDbObjectsTest.java @@ -36,7 +36,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -import javax.annotation.Nonnull; import java.sql.DriverManager; import java.sql.SQLException; @@ -44,7 +43,6 @@ * Test case-sensitive db object connection option. */ public class CaseSensitiveDbObjectsTest { - @Nonnull private static final String SCHEMA_TEMPLATE = """ CREATE TABLE "t1" ("group" bigint, "id" string, "val" bigint, PRIMARY KEY("group", "id")) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CopyCommandTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CopyCommandTest.java index 7884a56cb6a..7d1ef130e66 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CopyCommandTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CopyCommandTest.java @@ -59,7 +59,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import javax.annotation.Nonnull; import java.net.URI; import java.sql.SQLException; import java.util.ArrayList; @@ -185,7 +184,6 @@ void withExecutionContext(boolean withExecutionContext) throws RelationalExcepti } } - @Nonnull private static MutablePlanGenerationContext getMutablePlanGenerationContext(final String sql, final List exportedData) { final PreparedParams preparedParams = PreparedParams.of(Map.of(1, exportedData), Map.of()); final MutablePlanGenerationContext context = new MutablePlanGenerationContext(preparedParams, @@ -378,7 +376,6 @@ void invalidContinuationPlanHash() throws RelationalException, SQLException { }); } - @Nonnull private static Continuation continueExport(final int limit, final RelationalConnection connection, Continuation continuation, @@ -690,10 +687,10 @@ private void createSchemaTemplate(final boolean quoted, final RelationalStatemen " CREATE TABLE my_table (id bigint, col1 string, PRIMARY KEY(id))"); } - private static void createTemplateAndSchema(@Nonnull ConnectionUtils connUtils, - @Nonnull String templateName, - @Nonnull SchemaInfo schema, - @Nonnull String schemaTemplate) throws SQLException, RelationalException { + private static void createTemplateAndSchema(ConnectionUtils connUtils, + String templateName, + SchemaInfo schema, + String schemaTemplate) throws SQLException, RelationalException { connUtils.runCatalogStatement(stmt -> { stmt.executeUpdate("CREATE SCHEMA TEMPLATE " + templateName + " " + schemaTemplate); stmt.executeUpdate("CREATE DATABASE " + schema.databasePath); @@ -701,7 +698,7 @@ private static void createTemplateAndSchema(@Nonnull ConnectionUtils connUtils, }); } - private static FDBRecordStoreBase getBackingStore(@Nonnull RelationalConnection conn) throws SQLException, RelationalException { + private static FDBRecordStoreBase getBackingStore(RelationalConnection conn) throws SQLException, RelationalException { conn.unwrap(EmbeddedRelationalConnection.class).createNewTransaction(); final RecordLayerSchema recordLayerSchema = conn.unwrap(EmbeddedRelationalConnection.class).getRecordLayerDatabase().loadSchema(conn.getSchema()); @@ -713,9 +710,9 @@ private static FDBRecordStoreBase getBackingStore(@Nonnull RelationalCo return store; } - private static void updateIncarnation(@Nonnull ConnectionUtils connUtils, - @Nonnull SchemaInfo schema, - @Nonnull IntFunction updater) throws SQLException, RelationalException { + private static void updateIncarnation(ConnectionUtils connUtils, + SchemaInfo schema, + IntFunction updater) throws SQLException, RelationalException { connUtils.runAgainstConnection(schema.databasePath, schema.schemaName, conn -> { conn.setAutoCommit(false); final FDBRecordStoreBase store = getBackingStore(conn); @@ -724,7 +721,6 @@ private static void updateIncarnation(@Nonnull ConnectionUtils connUtils, }); } - @Nonnull private static String uuidForPath(final boolean quoted) { if (quoted) { return UUID.randomUUID().toString(); @@ -733,7 +729,6 @@ private static String uuidForPath(final boolean quoted) { } } - @Nonnull private static Map tenKeyValueRecords() { final Map data = new LinkedHashMap<>(); for (int i = 0; i < 10; i++) { @@ -750,8 +745,8 @@ private static String maybeQuote(final String path, final boolean quoted) { } } - private static void writeTestData(final ConnectionUtils connectionUtils, @Nonnull KeySpacePath path, - @Nonnull Map data) throws SQLException, RelationalException { + private static void writeTestData(final ConnectionUtils connectionUtils, KeySpacePath path, + Map data) throws SQLException, RelationalException { connectionUtils.runAgainstCatalog(conn -> { conn.setAutoCommit(false); final FDBRecordContext context = getRecordContext(conn); @@ -764,7 +759,7 @@ private static void writeTestData(final ConnectionUtils connectionUtils, @Nonnul }); } - private static void clearTestData(final ConnectionUtils connectionUtils, @Nonnull KeySpacePath path) throws SQLException, RelationalException { + private static void clearTestData(final ConnectionUtils connectionUtils, KeySpacePath path) throws SQLException, RelationalException { connectionUtils.runAgainstCatalog(conn -> { conn.setAutoCommit(false); final FDBRecordContext context = getRecordContext(conn); @@ -773,8 +768,8 @@ private static void clearTestData(final ConnectionUtils connectionUtils, @Nonnul }); } - private static void verifyTestData(final ConnectionUtils connectionUtils, @Nonnull KeySpacePath path, - @Nonnull Map expectedData) throws SQLException, RelationalException { + private static void verifyTestData(final ConnectionUtils connectionUtils, KeySpacePath path, + Map expectedData) throws SQLException, RelationalException { connectionUtils.runAgainstCatalog(conn -> { conn.setAutoCommit(false); final FDBRecordContext context = getRecordContext(conn); @@ -788,7 +783,7 @@ private static void verifyTestData(final ConnectionUtils connectionUtils, @Nonnu }); } - private static FDBRecordContext getRecordContext(final @Nonnull RelationalConnection conn) throws SQLException, RelationalException { + private static FDBRecordContext getRecordContext(final RelationalConnection conn) throws SQLException, RelationalException { EmbeddedRelationalConnection embeddedConn = conn.unwrap(EmbeddedRelationalConnection.class); embeddedConn.createNewTransaction(); return embeddedConn.getTransaction().unwrap(RecordContextTransaction.class).getContext(); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalExtension.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalExtension.java index 7944579ff05..4afe8bc1a1e 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalExtension.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalExtension.java @@ -41,8 +41,7 @@ import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ExtensionContext; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.io.Closeable; import java.sql.DriverManager; import java.sql.SQLException; @@ -50,7 +49,6 @@ public class EmbeddedRelationalExtension implements RelationalExtension, BeforeEachCallback, AfterEachCallback { - @Nonnull private final KeySpace keySpace; @Nullable @@ -59,10 +57,8 @@ public class EmbeddedRelationalExtension implements RelationalExtension, BeforeE @Nullable private EmbeddedRelationalEngine engine; - @Nonnull private final MetricRegistry storeTimer; - @Nonnull private final Options options; private StoreCatalog storeCatalog; private FDBDatabase database; @@ -73,7 +69,7 @@ public EmbeddedRelationalExtension() { this(Options.none()); } - public EmbeddedRelationalExtension(@Nonnull final Options options) { + public EmbeddedRelationalExtension(final Options options) { this(FDBTestEnvironment.randomClusterFile(), true, options); } @@ -120,7 +116,7 @@ private void setup() throws RelationalException, SQLException { } } - public EmbeddedRelationalDriver getDriver(@Nonnull final FormatVersion formatVersion) throws SQLException { + public EmbeddedRelationalDriver getDriver(final FormatVersion formatVersion) throws SQLException { return new EmbeddedRelationalDriver(makeEngine(database, formatVersion)); } @@ -133,7 +129,7 @@ private void makeDatabase(String clusterFile) throws RelationalException { } } - private EmbeddedRelationalEngine makeEngine(final @Nonnull FDBDatabase database, final @Nonnull FormatVersion formatVersion) { + private EmbeddedRelationalEngine makeEngine(final FDBDatabase database, final FormatVersion formatVersion) { final var config = new RecordLayerConfig.RecordLayerConfigBuilder() .setFormatVersion(formatVersion) .build(); @@ -162,18 +158,15 @@ public RelationalDriver getDriver() { return driver; } - @Nonnull public MetricRegistry getMetricRegistry() { return storeTimer; } - @Nonnull public static Resource newAsResource() throws Exception { return new Resource(new EmbeddedRelationalExtension()); } - @Nonnull - public static Resource newAsResource(@Nonnull final Options options) throws Exception { + public static Resource newAsResource(final Options options) throws Exception { return new Resource(new EmbeddedRelationalExtension(options)); } @@ -188,10 +181,9 @@ public EmbeddedRelationalExtension extensionForOtherCluster() throws SQLExceptio public static final class Resource implements Closeable { - @Nonnull private final EmbeddedRelationalExtension underlyingExtension; - Resource(@Nonnull final EmbeddedRelationalExtension underlyingExtension) throws Exception { + Resource(final EmbeddedRelationalExtension underlyingExtension) throws Exception { this.underlyingExtension = underlyingExtension; this.underlyingExtension.beforeEach(null); } @@ -205,7 +197,6 @@ public void close() { } } - @Nonnull public EmbeddedRelationalExtension getUnderlyingExtension() { return underlyingExtension; } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/FDBTupleTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/FDBTupleTest.java index cc205fdf941..028b4e71b2b 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/FDBTupleTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/FDBTupleTest.java @@ -30,15 +30,12 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import javax.annotation.Nonnull; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; class FDBTupleTest { - @Nonnull static final FDBTuple emptyTuple; - @Nonnull static final FDBTuple longTuple; static final Tuple fdbUnderlyingTuple = Tuple.from("five", 5L, 5.0f, diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/KeySpacePathParsingTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/KeySpacePathParsingTest.java index bda6f1afb19..56aa1071058 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/KeySpacePathParsingTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/KeySpacePathParsingTest.java @@ -44,8 +44,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; @@ -522,7 +521,6 @@ private static boolean isNull(final KeySpacePath path) { return path.getDirectory().getKeyType() == KeySpaceDirectory.KeyType.NULL; } - @Nonnull private static KeySpaceDirectory createStringLikeDirectory(String name, final boolean directory, final boolean constant, String constantValue) { if (directory) { return createDirectoryLayerDirectory(name, constant, constantValue); @@ -531,7 +529,6 @@ private static KeySpaceDirectory createStringLikeDirectory(String name, final bo } } - @Nonnull private static KeySpaceDirectory createDirectoryLayerDirectory(String name, final boolean constant, String constantValue) { if (constant) { return new DirectoryLayerDirectory(name, constantValue); @@ -540,7 +537,6 @@ private static KeySpaceDirectory createDirectoryLayerDirectory(String name, fina } } - @Nonnull private static KeySpaceDirectory createDirectory(String name, KeySpaceDirectory.KeyType type, boolean constant, Object constantValue) { if (constant) { @@ -577,17 +573,15 @@ private KeySpace sampleKeySpace() { ); } - @Nonnull private static KeySpaceDirectory constantStringDirectory(String name, String value) { return createDirectory(name, KeySpaceDirectory.KeyType.STRING, true, value); } - @Nonnull private static KeySpaceDirectory nullDirectory(String name) { return new KeySpaceDirectory(name, KeySpaceDirectory.KeyType.NULL); } - private List getResolvedValuesForKeySpacePath(@Nonnull KeySpacePath path, @Nonnull FDBRecordContext context) throws RelationalException { + private List getResolvedValuesForKeySpacePath(KeySpacePath path, FDBRecordContext context) throws RelationalException { try { List values = new ArrayList<>(); KeySpacePath currentPath = path; @@ -603,12 +597,11 @@ private List getResolvedValuesForKeySpacePath(@Nonnull KeySpacePath path } private static final class PathEntry { - @Nonnull private final String uriEntry; @Nullable private final Object pathEntry; - private PathEntry(@Nonnull final String uriEntry, @Nullable final Object pathEntry) { + private PathEntry(final String uriEntry, @Nullable final Object pathEntry) { this.uriEntry = uriEntry; this.pathEntry = pathEntry; } @@ -619,7 +612,6 @@ public String toString() { } } - @Nonnull private static AmbiguousHalf directoryAmbiguousHalf(String value) { final String name = "DirectoryLayer"; return new AmbiguousHalf(name, diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/LogAppenderRule.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/LogAppenderRule.java index 32701349825..984e153ea5a 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/LogAppenderRule.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/LogAppenderRule.java @@ -31,7 +31,6 @@ import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ExtensionContext; -import javax.annotation.Nonnull; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; @@ -40,11 +39,8 @@ public class LogAppenderRule implements BeforeEachCallback, AfterEachCallback, A private LogAppender logAppender; private Logger logger; - @Nonnull private final String name; - @Nonnull private final Class clazz; - @Nonnull private final Level level; private Level beforeLogLevel; @@ -65,13 +61,13 @@ public List getLogs() { } } - public LogAppenderRule(@Nonnull String name, @Nonnull Class clazz, @Nonnull Level level) { + public LogAppenderRule(String name, Class clazz, Level level) { this.name = name; this.clazz = clazz; this.level = level; } - public static LogAppenderRule of(@Nonnull String name, @Nonnull Class clazz, @Nonnull Level level) throws SQLException { + public static LogAppenderRule of(String name, Class clazz, Level level) throws SQLException { final var rule = new LogAppenderRule(name, clazz, level); rule.beforeEach(null); return rule; diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/MessageTupleTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/MessageTupleTest.java index 7879e053bef..c137cf46461 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/MessageTupleTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/MessageTupleTest.java @@ -35,7 +35,6 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import javax.annotation.Nonnull; import java.util.Collections; import java.util.List; @@ -105,7 +104,6 @@ void parseMessage() { Assertions.assertEquals(recordWithNonNullableArray, tupleWithNonNullableArray.parseMessage()); } - @Nonnull private DynamicMessage.Builder restaurantMessageBuilder(boolean nullableArray) throws Exception { final var location = RecordLayerTable.newBuilder(false) .setName("LOCATION") diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/OfflinePlanGenerationTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/OfflinePlanGenerationTest.java index d3d93166fa3..30e49b303e7 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/OfflinePlanGenerationTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/OfflinePlanGenerationTest.java @@ -43,7 +43,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -import javax.annotation.Nonnull; import java.util.List; import java.util.Map; import java.util.Optional; @@ -251,7 +250,6 @@ void offlinePlanSchemaVersions() throws Exception { .isNotEqualTo(planV1.getRecordQueryPlan().semanticHashCode()); } - @Nonnull private static RecordLayerSchemaTemplate booksTemplate(boolean withIndex, int version) { final var tableBuilder = RecordLayerTable.newBuilder(false) .setName("BOOKS") diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/PlaceholderCatalog.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/PlaceholderCatalog.java index 9c2abed8ee7..caf4d967ee8 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/PlaceholderCatalog.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/PlaceholderCatalog.java @@ -26,7 +26,7 @@ import com.google.protobuf.Descriptors; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.HashMap; import java.util.HashSet; import java.util.List; diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/PlanGenerationStackTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/PlanGenerationStackTest.java index ac08ab221d6..9901a1302de 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/PlanGenerationStackTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/PlanGenerationStackTest.java @@ -39,8 +39,7 @@ import org.junit.jupiter.params.provider.ArgumentsSource; import org.junit.jupiter.params.support.ParameterDeclarations; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.Optional; import java.util.regex.Pattern; import java.util.stream.Stream; @@ -173,7 +172,7 @@ public Stream provideArguments(final ParameterDeclarations @ParameterizedTest(name = "[{0}] {1}") @ArgumentsSource(RandomQueryProvider.class) - void queryTestHarness(int ignored, @Nonnull String query, @Nullable String error) throws Exception { + void queryTestHarness(int ignored, String query, @Nullable String error) throws Exception { final String schemaName = connection.getSchema(); final EmbeddedRelationalConnection embeddedConnection = (EmbeddedRelationalConnection) connection.connection; embeddedConnection.setAutoCommit(false); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/QueryPropertiesTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/QueryPropertiesTest.java index 8e6d94fe6b4..7f837257673 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/QueryPropertiesTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/QueryPropertiesTest.java @@ -44,7 +44,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -import javax.annotation.Nonnull; import java.sql.DriverManager; import java.sql.SQLException; import java.util.ArrayList; @@ -120,7 +119,7 @@ List testScan(Options options, long firstRestNo) throws RelationalExceptio } } - List getRestNoList(@Nonnull RelationalResultSet resultSet) throws SQLException { + List getRestNoList(RelationalResultSet resultSet) throws SQLException { List numbers = new ArrayList<>(); while (resultSet.next()) { numbers.add(resultSet.getLong("REST_NO")); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalArrayTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalArrayTest.java index 7b7d08030ce..87455210d75 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalArrayTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalArrayTest.java @@ -38,7 +38,6 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import javax.annotation.Nonnull; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; @@ -84,7 +83,7 @@ CREATE TABLE B(pk integer, uuid_null uuid array, primary key(pk)) @Order(1) public final SimpleDatabaseRule database = new SimpleDatabaseRule(RelationalArrayTest.class, SCHEMA_TEMPLATE); - public void insertQuery(@Nonnull String q) throws SQLException { + public void insertQuery(String q) throws SQLException { try (final var conn = DriverManager.getConnection(database.getConnectionUri().toString())) { conn.setSchema(database.getSchemaName()); conn.setAutoCommit(true); @@ -430,7 +429,7 @@ private void testArrays(int nullArrayIdx, int nonNullArrayIdx, List null } } - private void checkArrayElementsUsingGetResultSet(@Nonnull ResultSet arrayResultSet, int sqlType, List elements) throws SQLException { + private void checkArrayElementsUsingGetResultSet(ResultSet arrayResultSet, int sqlType, List elements) throws SQLException { final var arrayMetadata = arrayResultSet.getMetaData(); assertEquals(2, arrayMetadata.getColumnCount()); assertEquals(ResultSetMetaData.columnNoNulls, arrayMetadata.isNullable(1)); @@ -452,7 +451,7 @@ private void checkArrayElementsUsingGetResultSet(@Nonnull ResultSet arrayResultS assertFalse(arrayResultSet.next()); } - private void checkArrayElementsUsingGetArray(@Nonnull Object[] array, int sqlType, List elements) { + private void checkArrayElementsUsingGetArray(Object[] array, int sqlType, List elements) { assertEquals(elements.size(), array.length); for (int i = 0; i < elements.size(); i++) { final var object = array[i]; diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalConnectionRule.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalConnectionRule.java index f35d8d20555..6a0a8cdbb82 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalConnectionRule.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalConnectionRule.java @@ -33,7 +33,6 @@ import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ExtensionContext; -import javax.annotation.Nonnull; import java.net.URI; import java.sql.Array; import java.sql.DriverManager; @@ -127,7 +126,6 @@ public boolean isClosed() throws SQLException { return connection.isClosed(); } - @Nonnull @Override public RelationalDatabaseMetaData getMetaData() throws SQLException { return connection.getMetaData().unwrap(RelationalDatabaseMetaData.class); @@ -164,7 +162,6 @@ public String getSchema() throws SQLException { return connection.getSchema(); } - @Nonnull @Override public Options getOptions() { return connection.getOptions(); @@ -185,7 +182,6 @@ public URI getPath() { * type we run our JUnit tests against. * @return The underlying {@link EmbeddedRelationalConnection} connection. */ - @Nonnull public EmbeddedRelationalConnection getUnderlyingEmbeddedConnection() { return Assert.castUnchecked(connection, EmbeddedRelationalConnection.class); } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalExtension.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalExtension.java index 0945ccbad68..f3c3979c90c 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalExtension.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalExtension.java @@ -23,7 +23,7 @@ import com.apple.foundationdb.relational.api.EmbeddedRelationalEngine; import org.junit.jupiter.api.extension.Extension; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; public interface RelationalExtension extends Extension { diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalKeyspaceProviderTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalKeyspaceProviderTest.java index 480d6d651be..e7ec6bca8b4 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalKeyspaceProviderTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalKeyspaceProviderTest.java @@ -25,7 +25,6 @@ import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; -import javax.annotation.Nonnull; import java.net.URI; /** @@ -33,9 +32,7 @@ * that make sense. */ public class RelationalKeyspaceProviderTest { - @Nonnull private static final String defaultDomain = "DEFAULT_DOMAIN"; - @Nonnull private final RelationalKeyspaceProvider keyspaceProvider = RelationalKeyspaceProvider.newInstanceForTesting(); private void registerDefaultDomain() { diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalStatementRule.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalStatementRule.java index ec114970855..40c94c4f7e6 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalStatementRule.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalStatementRule.java @@ -31,7 +31,6 @@ import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ExtensionContext; -import javax.annotation.Nonnull; import java.sql.Connection; import java.sql.SQLException; import java.util.Iterator; @@ -55,30 +54,28 @@ public void beforeEach(ExtensionContext context) throws SQLException { statement = connection.createStatement(); } - @Nonnull @Override - public RelationalResultSet executeScan(@Nonnull String tableName, @Nonnull KeySet prefix, @Nonnull Options options) throws SQLException { + public RelationalResultSet executeScan(String tableName, KeySet prefix, Options options) throws SQLException { return statement.executeScan(tableName, prefix, options); } - @Nonnull @Override - public RelationalResultSet executeGet(@Nonnull String tableName, @Nonnull KeySet key, @Nonnull Options options) throws SQLException { + public RelationalResultSet executeGet(String tableName, KeySet key, Options options) throws SQLException { return statement.executeGet(tableName, key, options); } @Override - public int executeInsert(@Nonnull String tableName, @Nonnull List data, @Nonnull Options options) throws SQLException { + public int executeInsert(String tableName, List data, Options options) throws SQLException { return statement.executeInsert(tableName, data, options); } @Override - public int executeDelete(@Nonnull String tableName, @Nonnull Iterator keys, @Nonnull Options options) throws SQLException { + public int executeDelete(String tableName, Iterator keys, Options options) throws SQLException { return statement.executeDelete(tableName, keys); } @Override - public void executeDeleteRange(@Nonnull String tableName, @Nonnull KeySet prefix, @Nonnull Options options) throws SQLException { + public void executeDeleteRange(String tableName, KeySet prefix, Options options) throws SQLException { statement.executeDeleteRange(tableName, prefix, options); } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/SqlFunctionsTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/SqlFunctionsTest.java index 2334fed6c4a..c8e7067fec9 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/SqlFunctionsTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/SqlFunctionsTest.java @@ -30,10 +30,8 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -import javax.annotation.Nonnull; public class SqlFunctionsTest { - @Nonnull private static final String SCHEMA_TEMPLATE = """ create table t1(col1 bigint, col2 string, col3 integer, primary key(col1)) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/SystemCatalogQueryTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/SystemCatalogQueryTest.java index 6b217bc7151..8365031d613 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/SystemCatalogQueryTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/SystemCatalogQueryTest.java @@ -35,7 +35,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -import javax.annotation.Nonnull; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; @@ -70,7 +69,7 @@ public void teardown() throws Exception { runDdl("DROP SCHEMA TEMPLATE st"); } - private static void runDdl(@Nonnull final String ddl) throws Exception { + private static void runDdl(final String ddl) throws Exception { try (final var conn = DriverManager.getConnection("jdbc:embed:/__SYS")) { conn.setSchema("CATALOG"); try (final var statement = conn.createStatement()) { @@ -79,15 +78,15 @@ private static void runDdl(@Nonnull final String ddl) throws Exception { } } - private static void createDb(@Nonnull final String dbName) throws Exception { + private static void createDb(final String dbName) throws Exception { runDdl(String.format(Locale.ROOT, "CREATE DATABASE %s", dbName)); } - private static void createSchema(@Nonnull final String dbName, @Nonnull final String schemaName) throws Exception { + private static void createSchema(final String dbName, final String schemaName) throws Exception { runDdl(String.format(Locale.ROOT, "CREATE SCHEMA %s%s WITH TEMPLATE st", dbName, schemaName)); } - private static void dropDb(@Nonnull final String dbName) throws Exception { + private static void dropDb(final String dbName) throws Exception { runDdl(String.format(Locale.ROOT, "DROP DATABASE %s", dbName)); } @@ -157,7 +156,7 @@ public void selectDatabaseInfoWithPredicateAndProjectionWorks() throws Relationa } } - private static void shouldBe(@Nonnull final ResultSet resultSet, @Nonnull final Set> expected) throws SQLException { + private static void shouldBe(final ResultSet resultSet, final Set> expected) throws SQLException { assert !expected.isEmpty(); final int colCount = expected.stream().findFirst().get().size(); final ImmutableSet.Builder> actual = ImmutableSet.builder(); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/TransactionBoundDatabaseTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/TransactionBoundDatabaseTest.java index b82c51d28b8..247b347fc37 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/TransactionBoundDatabaseTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/TransactionBoundDatabaseTest.java @@ -61,8 +61,7 @@ import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.params.ParameterizedTest; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.net.URI; import java.sql.SQLException; import java.util.ArrayList; @@ -404,7 +403,6 @@ private static void saveSimpleRecord(final FDBRecordStore store, final String va .setField(getSimpleField(type), value).build()); } - @Nonnull private static RecordMetaData simpleMetaData() throws Descriptors.DescriptorValidationException { final DescriptorProtos.FileDescriptorProto.Builder protoBuilder = DescriptorProtos.FileDescriptorProto.newBuilder(); protoBuilder.addMessageTypeBuilder() @@ -452,7 +450,6 @@ private void importDataWithCopy(final EmbeddedRelationalConnection embeddedConne }); } - @Nonnull private List exportDataWithCopy(final EmbeddedRelationalConnection embeddedConnection, final URI sourceUri, final URI destUri) throws RelationalException, SQLException { List data = new ArrayList<>(); @@ -471,7 +468,6 @@ private List exportDataWithCopy(final EmbeddedRelationalConnection embed return data; } - @Nonnull private static List getExportedData(final RelationalResultSet resultSet) throws SQLException { List data = new ArrayList<>(); while (resultSet.next()) { @@ -502,10 +498,10 @@ private static Map getDataInPath(final EmbeddedRelationalConnectio } } - private void withTransactionBoundConnection(@Nonnull final EmbeddedRelationalConnection embeddedConnection, - @Nonnull final Options engineOptions, + private void withTransactionBoundConnection(final EmbeddedRelationalConnection embeddedConnection, + final Options engineOptions, @Nullable final KeySpace keySpace, - @Nonnull final ConnectionUtils.SQLConsumer action) + final ConnectionUtils.SQLConsumer action) throws RelationalException, SQLException { try (FDBRecordContext context = createNewContext(embeddedConnection)) { try (Transaction transaction = createRecordStoreAndRecordContextTransaction(embeddedConnection, context)) { @@ -515,24 +511,24 @@ private void withTransactionBoundConnection(@Nonnull final EmbeddedRelationalCon } } - private Transaction createRecordStoreAndRecordContextTransaction(@Nonnull final EmbeddedRelationalConnection embeddedConnection, - @Nonnull final FDBRecordContext context) throws SQLException, RelationalException { + private Transaction createRecordStoreAndRecordContextTransaction(final EmbeddedRelationalConnection embeddedConnection, + final FDBRecordContext context) throws SQLException, RelationalException { final FDBRecordStore store = getStore(embeddedConnection); final SchemaTemplate schemaTemplate = getSchemaTemplate(embeddedConnection); final FDBRecordStore newStore = store.asBuilder().setContext(context).open(); return new RecordStoreAndRecordContextTransaction(newStore, context, schemaTemplate); } - private void withTransactionBoundConnection(@Nonnull final Transaction transaction, - @Nonnull final FDBRecordContext context, - @Nonnull final ConnectionUtils.SQLConsumer action) throws SQLException, RelationalException { + private void withTransactionBoundConnection(final Transaction transaction, + final FDBRecordContext context, + final ConnectionUtils.SQLConsumer action) throws SQLException, RelationalException { withTransactionBoundConnection(new TransactionBoundEmbeddedRelationalEngine(), transaction, context, action); } - private void withTransactionBoundConnection(@Nonnull final EmbeddedRelationalEngine engine, - @Nonnull final Transaction transaction, - @Nonnull final FDBRecordContext context, - @Nonnull final ConnectionUtils.SQLConsumer action) throws SQLException, RelationalException { + private void withTransactionBoundConnection(final EmbeddedRelationalEngine engine, + final Transaction transaction, + final FDBRecordContext context, + final ConnectionUtils.SQLConsumer action) throws SQLException, RelationalException { EmbeddedRelationalDriver driver = new EmbeddedRelationalDriver(engine); try (RelationalConnection conn = driver.connect(dbRule.getConnectionUri(), transaction, Options.NONE)) { conn.setSchema("TEST_SCHEMA"); @@ -562,7 +558,7 @@ static SchemaTemplate getSchemaTemplate(EmbeddedRelationalConnection connection) return schemaTemplate; } - static FDBRecordContext createNewContext(@Nonnull EmbeddedRelationalConnection connection) throws RelationalException { + static FDBRecordContext createNewContext(EmbeddedRelationalConnection connection) throws RelationalException { return connection.getRecordLayerDatabase().getTransactionManager().createTransaction(Options.NONE).unwrap(FDBRecordContext.class); } } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/TransactionBoundDatabaseWithEnumTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/TransactionBoundDatabaseWithEnumTest.java index 058b81325fe..0717847d64a 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/TransactionBoundDatabaseWithEnumTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/TransactionBoundDatabaseWithEnumTest.java @@ -52,7 +52,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -import javax.annotation.Nonnull; import java.sql.SQLException; import static org.assertj.core.api.Assertions.fail; @@ -240,7 +239,7 @@ private static RecordMetaData createRecordMetaData() { return metaDataBuilder.build(); } - private static FDBRecordStoreBase getStore(@Nonnull EmbeddedRelationalConnection connection, @Nonnull FDBRecordContext context) throws RelationalException, SQLException { + private static FDBRecordStoreBase getStore(EmbeddedRelationalConnection connection, FDBRecordContext context) throws RelationalException, SQLException { connection.setAutoCommit(false); connection.createNewTransaction(); SubspaceProvider subspaceProvider = connection.getRecordLayerDatabase().loadRecordStore("TEST_SCHEMA", FDBRecordStoreBase.StoreExistenceCheck.ERROR_IF_NO_INFO_AND_NOT_EMPTY) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/UniqueIndexTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/UniqueIndexTests.java index 843c57248ea..b906c3ea3cc 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/UniqueIndexTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/UniqueIndexTests.java @@ -32,7 +32,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -import javax.annotation.Nonnull; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; @@ -76,7 +75,7 @@ CREATE TABLE T5(t5_p bigint, t5_a bigint, t5_b bigint, t5_c bigint, t5_d bigint, @Order(3) public final RelationalStatementRule statement = new RelationalStatementRule(connection); - private void insertUniqueRecordsToTable(@Nonnull List toInsert, @Nonnull String tableName) { + private void insertUniqueRecordsToTable(List toInsert, String tableName) { try { final var count = statement.executeInsert(tableName, toInsert); Assertions.assertEquals(count, toInsert.size()); @@ -85,7 +84,7 @@ private void insertUniqueRecordsToTable(@Nonnull List toInsert } } - private void checkErrorOnNonUniqueInsertionsToTable(@Nonnull List toInsert, @Nonnull String tableName) { + private void checkErrorOnNonUniqueInsertionsToTable(List toInsert, String tableName) { boolean foundError = false; try { final var count = statement.executeInsert(tableName, toInsert); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/Utils.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/Utils.java index 593ba2c910f..b3dc60582af 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/Utils.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/Utils.java @@ -33,7 +33,6 @@ import com.apple.foundationdb.relational.recordlayer.util.ExceptionUtil; import com.apple.foundationdb.relational.util.Environment; -import javax.annotation.Nonnull; import java.sql.Connection; import java.sql.SQLException; import java.sql.Types; @@ -140,8 +139,8 @@ public static void enableCascadesDebugger() { Debugger.setup(); } - public static void setConnectionOptions(@Nonnull final Connection connection, - @Nonnull final Options connectionOptions) throws SQLException { + public static void setConnectionOptions(final Connection connection, + final Options connectionOptions) throws SQLException { final var relationalConnection = connection.unwrap(RelationalConnection.class); for (final var option : connectionOptions.entries()) { relationalConnection.setOption(option.getKey(), option.getValue()); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalogImplTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalogImplTest.java index 21981cb654a..52710f90d01 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalogImplTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalogImplTest.java @@ -47,7 +47,6 @@ import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.MethodSource; -import javax.annotation.Nonnull; import java.net.URI; import java.util.Locale; import java.util.UUID; @@ -455,8 +454,7 @@ public boolean doesWrite(final SchemaExistsBehavior behavior) { * the template-existence assertion. Returns the database URI so callers can address the * schema. */ - @Nonnull - private URI preSaveExistingSchema(@Nonnull String dbSuffix) throws RelationalException { + private URI preSaveExistingSchema(String dbSuffix) throws RelationalException { final String dbId = "/TEST/" + dbSuffix; final Schema existing = generateTestSchema("s", dbId, INITIAL_TEMPLATE, INITIAL_VERSION); final SchemaTemplate newerVersion = generateTestSchemaTemplate(INITIAL_TEMPLATE, INITIAL_VERSION + 1); @@ -475,8 +473,7 @@ private URI preSaveExistingSchema(@Nonnull String dbSuffix) throws RelationalExc } /** Build the schema used for the second save based on {@code shape}. */ - @Nonnull - private Schema secondSaveSchema(@Nonnull URI dbId, @Nonnull SecondSaveShape shape) { + private Schema secondSaveSchema(URI dbId, SecondSaveShape shape) { return switch (shape) { case IDENTICAL -> generateTestSchema("s", dbId.toString(), INITIAL_TEMPLATE, INITIAL_VERSION); case NEWER_VERSION -> generateTestSchema("s", dbId.toString(), INITIAL_TEMPLATE, INITIAL_VERSION + 1); @@ -487,7 +484,7 @@ private Schema secondSaveSchema(@Nonnull URI dbId, @Nonnull SecondSaveShape shap } /** Reload the schema at {@code (dbId, "s")} and assert the persisted template matches. */ - private void assertPersistedTemplateEquals(@Nonnull URI dbId, @Nonnull String expectedTemplateName, + private void assertPersistedTemplateEquals(URI dbId, String expectedTemplateName, int expectedVersion) throws RelationalException { try (Transaction txn = new RecordContextTransaction(fdb.openContext())) { final Schema reloaded = storeCatalog.loadSchema(txn, dbId, "s"); @@ -505,7 +502,7 @@ static Stream saveSchemaExistsBehavior() { /** Test a saveSchema with various exists behaviors when the schema already exists. **/ @ParameterizedTest @MethodSource - void saveSchemaExistsBehavior(@Nonnull SecondSaveShape shape, @Nonnull SchemaExistsBehavior behavior) throws RelationalException { + void saveSchemaExistsBehavior(SecondSaveShape shape, SchemaExistsBehavior behavior) throws RelationalException { URI dbId = preSaveExistingSchema("db_error_" + shape.name().toLowerCase(Locale.ROOT)); final Schema second = secondSaveSchema(dbId, shape); if (shape.succeeds(behavior)) { @@ -531,7 +528,7 @@ void saveSchemaExistsBehavior(@Nonnull SecondSaveShape shape, @Nonnull SchemaExi /** Test a saveSchema with various exists behaviors when the schema does not already exist. **/ @ParameterizedTest @EnumSource(SchemaExistsBehavior.class) - void saveSchemaExistsBehaviorWithNothing(@Nonnull SchemaExistsBehavior behavior) throws RelationalException { + void saveSchemaExistsBehaviorWithNothing(SchemaExistsBehavior behavior) throws RelationalException { final String dbId = "/TEST/" + "schema_exists_with_nothing" + behavior; final Schema initialSchema = generateTestSchema("s", dbId, INITIAL_TEMPLATE, INITIAL_VERSION); try (Transaction txn = new RecordContextTransaction(fdb.openContext())) { @@ -566,10 +563,10 @@ public static Stream concurrentSaveSchema() { */ @ParameterizedTest @MethodSource - void concurrentSaveSchema(@Nonnull SchemaExistsBehavior behavior1, - @Nonnull SchemaExistsBehavior behavior2, - @Nonnull SecondSaveShape shape1, - @Nonnull SecondSaveShape shape2, + void concurrentSaveSchema(SchemaExistsBehavior behavior1, + SchemaExistsBehavior behavior2, + SecondSaveShape shape1, + SecondSaveShape shape2, boolean txn2UnrelatedWrite) throws RelationalException { // We only exercise pairs where BOTH sides return from saveSchema — otherwise the // synchronous throw kills the setup and there's no commit ordering to observe. diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalogTestBase.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalogTestBase.java index d35490cb6b6..51218010a4b 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalogTestBase.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalogTestBase.java @@ -42,7 +42,6 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import javax.annotation.Nonnull; import java.net.URI; import java.sql.SQLException; import java.util.ArrayList; @@ -286,30 +285,28 @@ void testAllTheSchemas() throws RelationalException, SQLException { } @SuppressWarnings({"SameParameterValue"}) - static RecordLayerSchema generateTestSchema(@Nonnull final String schemaName, - @Nonnull final String databaseId, - @Nonnull final String schemaTemplateName, + static RecordLayerSchema generateTestSchema(final String schemaName, + final String databaseId, + final String schemaTemplateName, final int schemaTemplateVersion) { return generateTestSchema(schemaName, databaseId, schemaTemplateName, schemaTemplateVersion, false); } @SuppressWarnings({"SameParameterValue"}) - static RecordLayerSchema generateTestSchema(@Nonnull final String schemaName, - @Nonnull final String databaseId, - @Nonnull final String schemaTemplateName, + static RecordLayerSchema generateTestSchema(final String schemaName, + final String databaseId, + final String schemaTemplateName, final int schemaTemplateVersion, boolean withViews) { final var template = generateTestSchemaTemplate(schemaTemplateName, schemaTemplateVersion, withViews); return template.generateSchema(databaseId, schemaName); } - @Nonnull - static RecordLayerSchemaTemplate generateTestSchemaTemplate(@Nonnull final String schemaTemplateName, int version) { + static RecordLayerSchemaTemplate generateTestSchemaTemplate(final String schemaTemplateName, int version) { return generateTestSchemaTemplate(schemaTemplateName, version, false); } - @Nonnull - static RecordLayerSchemaTemplate generateTestSchemaTemplate(@Nonnull final String schemaTemplateName, int version, boolean withViews) { + static RecordLayerSchemaTemplate generateTestSchemaTemplate(final String schemaTemplateName, int version, boolean withViews) { final var builder = RecordLayerSchemaTemplate .newBuilder() .addTable( diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerColumnTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerColumnTests.java index e7ccaf6aed0..573e80b5bf2 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerColumnTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerColumnTests.java @@ -27,7 +27,6 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import javax.annotation.Nonnull; import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; @@ -63,7 +62,6 @@ void basicCopy() { } } - @Nonnull static Stream testDiffersFromBlah() { return Stream.of( Arguments.of( @@ -107,7 +105,7 @@ static Stream testDiffersFromBlah() { @ParameterizedTest(name = "testDiffersFromBlah[{1}]") @MethodSource - void testDiffersFromBlah(@Nonnull RecordLayerColumn differentColumn, @Nonnull String toString) { + void testDiffersFromBlah(RecordLayerColumn differentColumn, String toString) { try (AutoCloseableSoftAssertions softly = new AutoCloseableSoftAssertions()) { softly.assertThat(differentColumn) .hasToString(toString) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerViewTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerViewTests.java index 82a1e3369fc..88527d19eb1 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerViewTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerViewTests.java @@ -25,7 +25,6 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import javax.annotation.Nonnull; import java.util.function.Function; import static org.assertj.core.api.Assertions.assertThat; @@ -35,7 +34,6 @@ */ public class RecordLayerViewTests { - @Nonnull private static Function createMockCompiler() { return (Boolean parameter) -> null; } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/SchemaTemplateSerDeTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/SchemaTemplateSerDeTests.java index ff5efbf31c8..942947baf29 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/SchemaTemplateSerDeTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/SchemaTemplateSerDeTests.java @@ -60,7 +60,6 @@ import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; -import javax.annotation.Nonnull; import java.net.URI; import java.sql.SQLException; import java.util.BitSet; @@ -87,7 +86,6 @@ public static void setup() { Utils.enableCascadesDebugger(); } - @Nonnull private static RecordLayerSchemaTemplate basicTestTemplate() { return RecordLayerSchemaTemplate.newBuilder().setName("TestSchemaTemplate") .addTable(RecordLayerTable.newBuilder(false) @@ -134,7 +132,7 @@ private static RecordLayerSchemaTemplate basicTestTemplate() { .build(); } - private static RecordLayerSchemaTemplate getTestRecordLayerSchemaTemplate(@Nonnull Map>> template) { + private static RecordLayerSchemaTemplate getTestRecordLayerSchemaTemplate(Map>> template) { final var builder = RecordLayerSchemaTemplate.newBuilder().setName("TestSchemaTemplate"); for (var entry : template.entrySet()) { final var tableBuilder = RecordLayerTable.newBuilder(false) @@ -264,7 +262,6 @@ void readableIndexBitsetWorksCorrectly() throws RelationalException { Assertions.assertEquals(BitSet.valueOf(new long[]{0b00001111}), template.getIndexEntriesAsBitset(Optional.empty())); } - @Nonnull static Stream badSchemaTemplateGenerationsTestcaseProvider() { final var fieldOptions1 = DescriptorProtos.FieldOptions.newBuilder().setDeprecated(true).build(); final var fieldOptions2 = DescriptorProtos.FieldOptions.newBuilder().setDeprecated(false).build(); @@ -598,8 +595,7 @@ void schemaTemplateToBuilderPreservesIntermingledTablesFlag(boolean intermingleT Assertions.assertEquals(intermingleTables, sampleRecordSchemaTemplate.isIntermingleTables()); } - @Nonnull - private static RecordMetadataDeserializerWithPeekingFunctionSupplier recMetadataSampleWithFunctions(@Nonnull final String... functions) { + private static RecordMetadataDeserializerWithPeekingFunctionSupplier recMetadataSampleWithFunctions(final String... functions) { final var schemaTemplateBuilder = RecordLayerSchemaTemplate.newBuilder() .setName("TestSchemaTemplate") .setVersion(42) @@ -927,7 +923,6 @@ void testFindViewByNameReturnsEmpty() { Assertions.assertFalse(viewOpt.isPresent()); } - @Nonnull private static Descriptors.FileDescriptor createEscapedRecordTypesDescriptor() { DescriptorProtos.FileDescriptorProto fileDescriptorProto = DescriptorProtos.FileDescriptorProto.newBuilder() .setName("test_schema_with_escaping.proto") @@ -973,7 +968,6 @@ private static Descriptors.FileDescriptor createEscapedRecordTypesDescriptor() { } } - @Nonnull private static Descriptors.FileDescriptor createRecordTypesDescriptorWithMalformedEscaping() { DescriptorProtos.FileDescriptorProto fileDescriptorProto = DescriptorProtos.FileDescriptorProto.newBuilder() .setName("test_schema_with_malformed_escaping.proto") @@ -1021,17 +1015,16 @@ private static Descriptors.FileDescriptor createRecordTypesDescriptorWithMalform private static final class RecordMetadataDeserializerWithPeekingFunctionSupplier extends RecordMetadataDeserializer { - @Nonnull private final Map invocationsCount; - public RecordMetadataDeserializerWithPeekingFunctionSupplier(@Nonnull final RecordMetaData recordMetaData) { + public RecordMetadataDeserializerWithPeekingFunctionSupplier(final RecordMetaData recordMetaData) { super(recordMetaData); invocationsCount = new HashMap<>(); hookInvokedRoutines(builder, invocationsCount); } - private static void hookInvokedRoutines(@Nonnull final RecordLayerSchemaTemplate.Builder schemaBuilder, - @Nonnull final Map invocationsCount) { + private static void hookInvokedRoutines(final RecordLayerSchemaTemplate.Builder schemaBuilder, + final Map invocationsCount) { final List invokedRoutines = schemaBuilder.getInvokedRoutines(); for (RecordLayerInvokedRoutine routine : invokedRoutines) { final String name = routine.getName(); @@ -1046,15 +1039,14 @@ private static void hookInvokedRoutines(@Nonnull final RecordLayerSchemaTemplate } } - boolean hasNoCompilationRequestsFor(@Nonnull final String functionName) { + boolean hasNoCompilationRequestsFor(final String functionName) { return invocationsCount.get(functionName) == null; } - boolean hasOneCompilationRequestFor(@Nonnull final String functionName) { + boolean hasOneCompilationRequestFor(final String functionName) { return 1 == invocationsCount.get(functionName); } - @Nonnull public PlanGenerator getPlanGenerator() throws RelationalException, SQLException { final var metricCollector = NoOpMetricCollector.INSTANCE; diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metric/StoreTimerMetricCollectorFromFDBRecordContextTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metric/StoreTimerMetricCollectorFromFDBRecordContextTest.java index 09ddc0cc38a..a5b2a2ad338 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metric/StoreTimerMetricCollectorFromFDBRecordContextTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metric/StoreTimerMetricCollectorFromFDBRecordContextTest.java @@ -34,7 +34,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -import javax.annotation.Nonnull; import java.net.URI; import java.sql.SQLException; import java.util.function.Consumer; @@ -119,7 +118,7 @@ private void setupAndExecuteWithConnection(Consumer collector.getAverageTimeMicrosForEvent(RelationalMetric.RelationalEvent.LEX_PARSE), "LEX_PARSE event should be registered with the metricCollector"); Assertions.assertDoesNotThrow(() -> collector.getAverageTimeMicrosForEvent(RelationalMetric.RelationalEvent.NORMALIZE_QUERY), @@ -136,7 +135,7 @@ private static void testGeneralMetrics(@Nonnull MetricCollector collector) { "TOTAL_GET_PLAN_QUERY event should be registered with the metricCollector"); } - private static void testCacheMissSpecificMetrics(@Nonnull MetricCollector collector) { + private static void testCacheMissSpecificMetrics(MetricCollector collector) { // true event Assertions.assertDoesNotThrow(() -> collector.getAverageTimeMicrosForEvent(RelationalMetric.RelationalEvent.CACHE_LOOKUP), "CACHE_LOOKUP event should be registered with the metricCollector"); @@ -155,7 +154,7 @@ private static void testCacheMissSpecificMetrics(@Nonnull MetricCollector collec "PLAN_CACHE_TERTIARY_HIT event should not be registered with the metricCollector"); } - private static void testCacheHitSpecificMetrics(@Nonnull MetricCollector collector) { + private static void testCacheHitSpecificMetrics(MetricCollector collector) { // false events Assertions.assertThrows(UncheckedRelationalException.class, () -> collector.getAverageTimeMicrosForEvent(RelationalMetric.RelationalEvent.GENERATE_CONTINUED_PLAN), "GENERATE_CONTINUED_PLAN event should not be registered with the metricCollector"); @@ -176,7 +175,7 @@ private static void testCacheHitSpecificMetrics(@Nonnull MetricCollector collect "PLAN_CACHE_TERTIARY_HIT event should be registered with the metricCollector"); } - private static void testExecuteContinuationSpecificMetrics(@Nonnull MetricCollector collector) { + private static void testExecuteContinuationSpecificMetrics(MetricCollector collector) { // false events Assertions.assertThrows(UncheckedRelationalException.class, () -> collector.getAverageTimeMicrosForEvent(RelationalMetric.RelationalEvent.GENERATE_LOGICAL_PLAN), "GENERATE_LOGICAL_PLAN event should not be registered with the metricCollector"); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/storage/BackingLocatableResolverStoreTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/storage/BackingLocatableResolverStoreTest.java index 01a5d7d10fa..986080b688a 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/storage/BackingLocatableResolverStoreTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/storage/BackingLocatableResolverStoreTest.java @@ -63,8 +63,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.net.URI; import java.nio.charset.StandardCharsets; import java.sql.SQLException; @@ -128,10 +127,10 @@ private static class TransactionBoundLocatableResolverDatabase extends AbstractD private final StoreCatalog catalog; private Transaction txn; - public TransactionBoundLocatableResolverDatabase(@Nonnull URI dbPath, - @Nonnull StorageCluster cluster, - @Nonnull LocatableResolver resolver, - @Nonnull StoreCatalog catalog) { + public TransactionBoundLocatableResolverDatabase(URI dbPath, + StorageCluster cluster, + LocatableResolver resolver, + StoreCatalog catalog) { super(NoOpMetadataOperationsFactory.INSTANCE, NoOpQueryFactory.INSTANCE, null, Options.NONE); this.dbPath = dbPath; this.transactionManager = cluster.getTransactionManager(); @@ -155,7 +154,7 @@ public void close() throws RelationalException { } @Override - public BackingStore loadRecordStore(@Nonnull String schemaId, @Nonnull FDBRecordStoreBase.StoreExistenceCheck existenceCheck) throws RelationalException { + public BackingStore loadRecordStore(String schemaId, FDBRecordStoreBase.StoreExistenceCheck existenceCheck) throws RelationalException { return BackingLocatableResolverStore.create(resolver, getCurrentTransaction()); } @@ -669,12 +668,10 @@ private void insertResolverState(RelationalStatement statement, int version, Str statement.executeInsert(LocatableResolverMetaDataProvider.RESOLVER_STATE_TYPE_NAME, struct, options); } - @Nonnull private RelationalResultSet scanResolverStates(RelationalStatement statement) throws SQLException { return scanResolverStates(statement, 0, ContinuationImpl.BEGIN); } - @Nonnull private RelationalResultSet scanResolverStates(RelationalStatement statement, int maxRows, Continuation continuation) throws SQLException { Options options = Options.builder() .withOption(Options.Name.MAX_ROWS, maxRows) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/util/MemoizedFunctionTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/util/MemoizedFunctionTest.java index e8c590608a2..cadd61c6cf7 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/util/MemoizedFunctionTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/util/MemoizedFunctionTest.java @@ -24,7 +24,6 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -36,7 +35,6 @@ private static final class StatefulFunction { private Set seenValues; - @Nonnull private final Function underlying; private StatefulFunction(Function underlying) { From 4ec37d7a55ff6251caf3038a80d2f18479859032 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Wed, 2 Sep 2026 16:54:41 -0400 Subject: [PATCH 04/42] WIP: wire up NullAway for fdb-relational-core, fix errors in progress Adds NullAway + jspecify wiring in fdb-relational-core.gradle (AnnotatedPackages = com.apple.foundationdb.relational.{api,recordlayer, transactionbound,util}), fills two @NullMarked gaps left by the mechanical phase (api/exceptions, api/options package-info), and works through the resulting compileJava errors file by file. Note: fdb-relational-core.gradle currently has a TEMP-DIAGNOSTIC -Xmaxerrs bump to see the full error list past javac's 100-error cap; this must be removed before this branch is considered done. This is a WIP checkpoint mid compile-fix loop -- compileJava is not yet clean. Not all files are finished (RecordLayerIterator, MessageTuple, LogicalOperator, functions/*, RecordLayerStoreCatalog fixed; QueryPlan, CopyPlan, PlanGenerator, MutablePlanGenerationContext, Expression and a few others still outstanding). --- .../fdb-relational-core.gradle | 26 +++++++ .../api/EmbeddedRelationalDriver.java | 11 ++- .../relational/api/MutableRowStruct.java | 6 +- .../relational/api/RowStruct.java | 25 ++++++ .../catalog/NoOpSchemaTemplateCatalog.java | 13 +++- .../relational/api/ddl/DdlQuery.java | 1 + .../relational/api/ddl/ProtobufDdlUtil.java | 13 +++- .../api/exceptions/package-info.java | 3 + .../api/metrics/MetricCollector.java | 3 +- .../relational/api/options/package-info.java | 3 + .../recordlayer/AbstractDatabase.java | 5 +- .../AbstractEmbeddedStatement.java | 9 +++ .../recordlayer/CatalogMetaData.java | 20 +++-- .../recordlayer/ContinuationImpl.java | 17 +++++ .../recordlayer/DirectScannable.java | 6 ++ .../EmbeddedRelationalConnection.java | 28 +++++-- .../EmbeddedRelationalPreparedStatement.java | 10 ++- .../EmbeddedRelationalStatement.java | 19 ++++- .../recordlayer/IteratorResultSet.java | 6 ++ .../relational/recordlayer/KeySpaceUtils.java | 5 +- .../relational/recordlayer/MessageTuple.java | 3 + .../relational/recordlayer/QueryExecutor.java | 1 + .../recordlayer/RecordContextTransaction.java | 3 +- .../recordlayer/RecordLayerIterator.java | 61 +++++++++++---- .../recordlayer/RecordLayerResultSet.java | 11 ++- .../recordlayer/RecordLayerSchema.java | 2 + .../RecordLayerStorageCluster.java | 2 +- .../recordlayer/RecordStoreIndex.java | 1 + .../recordlayer/RecordTypeScannable.java | 5 +- .../recordlayer/RecordTypeTable.java | 11 ++- .../catalog/CatalogMetaDataProvider.java | 3 + .../catalog/RecordLayerStoreCatalog.java | 9 +-- ...RecordLayerStoreSchemaTemplateCatalog.java | 12 ++- .../catalog/TransactionBoundDatabase.java | 5 +- .../ddl/DropDatabaseConstantAction.java | 3 +- .../RecordLayerMetadataOperationsFactory.java | 6 ++ .../recordlayer/metadata/DataTypeUtils.java | 23 +++--- .../metadata/RecordLayerColumn.java | 3 + .../metadata/RecordLayerIndex.java | 17 ++++- .../metadata/RecordLayerInvokedRoutine.java | 4 + .../metadata/RecordLayerSchemaTemplate.java | 31 ++++++-- .../metadata/RecordLayerTable.java | 4 + .../recordlayer/metadata/RecordLayerView.java | 4 + .../serde/FileDescriptorSerializer.java | 13 +++- .../serde/RecordMetadataSerializer.java | 5 +- .../metric/StoreTimerMetricCollector.java | 33 +++++--- .../recordlayer/query/AstNormalizer.java | 26 ++++--- .../recordlayer/query/FieldValueTrieNode.java | 2 +- .../recordlayer/query/Literals.java | 6 +- .../recordlayer/query/LogicalOperator.java | 3 +- .../NormalizedQueryExecutionContext.java | 4 + .../recordlayer/query/OrderByExpression.java | 9 ++- .../recordlayer/query/PlanContext.java | 4 + .../recordlayer/query/SemanticAnalyzer.java | 76 +++++++++++++++---- .../relational/recordlayer/query/Star.java | 6 +- .../query/cache/MultiStageCache.java | 1 + .../query/cache/RelationalPlanCache.java | 16 ++-- .../ddl/MaterializedViewIndexGenerator.java | 22 ++++-- .../query/ddl/OnSourceIndexGenerator.java | 19 ++++- .../query/functions/CompiledSqlFunction.java | 4 + .../functions/UserDefinedFunctionBuilder.java | 3 + .../UserDefinedMacroFunctionBuilder.java | 8 +- .../query/visitors/BaseVisitor.java | 5 ++ .../query/visitors/ExpressionVisitor.java | 39 +++++++--- .../query/visitors/IdentifierVisitor.java | 9 +-- .../query/visitors/QueryVisitor.java | 20 ++++- .../BackingLocatableResolverStore.java | 24 +++++- .../LocatableResolverMetaDataProvider.java | 21 +++-- .../recordlayer/storage/StoreConfig.java | 3 +- .../expression/ExpressionFactoryImpl.java | 14 +++- .../statement/UpdateStatementImpl.java | 21 ++++- .../recordlayer/util/ExceptionUtil.java | 5 +- .../relational/recordlayer/util/Hex.java | 3 +- .../recordlayer/util/TypeUtils.java | 17 ++++- ...nsactionBoundEmbeddedRelationalEngine.java | 2 + .../catalog/HollowStoreCatalog.java | 3 + .../relational/util/NullableArrayUtils.java | 5 +- .../relational/util/Supplier.java | 4 +- .../query/cache/MultiStageCacheTests.java | 2 +- .../query/cache/NoOpMetricCollector.java | 2 +- 80 files changed, 722 insertions(+), 190 deletions(-) diff --git a/fdb-relational-core/fdb-relational-core.gradle b/fdb-relational-core/fdb-relational-core.gradle index 7a135d83328..8d15c25b727 100644 --- a/fdb-relational-core/fdb-relational-core.gradle +++ b/fdb-relational-core/fdb-relational-core.gradle @@ -21,6 +21,7 @@ plugins { id 'java-test-fixtures' alias(libs.plugins.jmh) + alias(libs.plugins.errorprone) } apply from: rootProject.file('gradle/antlr.gradle') @@ -45,6 +46,9 @@ dependencies { antlr(libs.antlr) + errorprone(libs.errorprone.core) + errorprone(libs.nullaway) + testImplementation(libs.bundles.test.impl) testImplementation(libs.bundles.test.runtime) testCompileOnly(libs.bundles.test.compileOnly) @@ -59,6 +63,7 @@ dependencies { testFixturesImplementation(libs.protobuf) testFixturesImplementation(libs.assertj) testFixturesImplementation(libs.jsr305) + testFixturesCompileOnly(libs.jspecify) // This is included just for ResultSetAssert. It does a bunch of this // Type.Record record = ProtobufDdlUtil.recordFromDescriptor(((Message) colValue).getDescriptorForType()); testFixturesImplementation(project(coreProject)) @@ -74,6 +79,27 @@ tasks.withType(Test).configureEach { theTask -> theTask.testFramework.options.includeEngines.add('junit-jupiter') } +// jspecify + NullAway null-checking, scoped to this module. See @NullMarked package-info.java +// files under com.apple.foundationdb.relational.{api,recordlayer,transactionbound,util} in this +// module (fdb-relational-core also has non-@NullMarked test-only packages, e.g. +// com.apple.foundationdb.relational.memory / .autotest under src/test, which fall outside these +// prefixes and are therefore left unchecked). Generated ANTLR parser code +// (com.apple.foundationdb.relational.generated) and generated protobuf code +// (com.apple.foundationdb.relational.continuation, com.apple.foundationdb.relational.copy, +// com.apple.foundationdb.record) already live outside these package prefixes, so no +// UnannotatedSubPackages carve-out is needed. +tasks.withType(JavaCompile).configureEach { + options.errorprone { + disableAllChecks = true + error("NullAway") + option("NullAway:AnnotatedPackages", "com.apple.foundationdb.relational.api,com.apple.foundationdb.relational.recordlayer,com.apple.foundationdb.relational.transactionbound,com.apple.foundationdb.relational.util") + option("NullAway:JSpecifyMode", "true") + option("NullAway:AcknowledgeRestrictiveAnnotations", "true") + } + // TEMP-DIAGNOSTIC: remove before finishing -- see full error list instead of javac's default 100-cap. + options.compilerArgs << "-Xmaxerrs" << "10000" +} + publishing { publications { library(MavenPublication) { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalDriver.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalDriver.java index f7fc1c6119c..f3f2d390205 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalDriver.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalDriver.java @@ -43,7 +43,10 @@ public class EmbeddedRelationalDriver implements RelationalDriver { private EmbeddedRelationalEngine engine; - public EmbeddedRelationalDriver(@Nullable EmbeddedRelationalEngine engine) throws SQLException { + // engine is dereferenced unconditionally below (e.g. engine.getStorageClusters()) with no null check, + // and no caller in this codebase ever passes null, so @Nullable here was never actually honored; + // require it, matching actual usage. + public EmbeddedRelationalDriver(EmbeddedRelationalEngine engine) throws SQLException { this.engine = engine; } @@ -58,7 +61,11 @@ public RelationalConnection connect(URI url, return connect(url, null, connectionOptions); } - @SuppressWarnings("PMD.CloseResource") // returns connection outliving auto-closeable object. Should consider refactoring + @SuppressWarnings({"PMD.CloseResource", "NullAway"}) + // PMD: returns connection outliving auto-closeable object. Should consider refactoring + // NullAway: per the java.sql.Driver#connect(String, Properties) contract this method mirrors, returning + // null here for a URL this driver doesn't understand is correct, expected behavior (relied upon by + // java.sql.DriverManager when trying multiple registered drivers), not a bug. public RelationalConnection connect(URI url, @Nullable Transaction existingTransaction, Options connectionOptions) throws SQLException { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/MutableRowStruct.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/MutableRowStruct.java index f344b177f9c..77720d62f3e 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/MutableRowStruct.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/MutableRowStruct.java @@ -24,19 +24,23 @@ import com.apple.foundationdb.relational.api.exceptions.InvalidColumnReferenceException; +import org.jspecify.annotations.Nullable; import java.sql.SQLException; import java.util.Objects; @API(API.Status.EXPERIMENTAL) public class MutableRowStruct extends RowStruct { + // null until setRow() is called with a non-null row, or after setRow(null) (e.g. once the underlying cursor is + // exhausted); see hasRow() and getObjectInternal() below. + @Nullable private Row row; public MutableRowStruct(StructMetaData metaData) { super(metaData); } - public void setRow(Row next) { + public void setRow(@Nullable Row next) { this.row = next; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/RowStruct.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/RowStruct.java index 5b3d2364bc2..5ed84cf148c 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/RowStruct.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/RowStruct.java @@ -85,6 +85,11 @@ public boolean getBoolean(String columnLabel) throws SQLException { } @Override + // RelationalStruct#getBytes(int) (in the not-yet-migrated fdb-relational-api module) has no explicit @Nullable + // annotation, so NullAway treats it as @NonNull; this genuinely returns null for a SQL NULL column, same as + // before this migration. (A `return` statement can't itself carry @SuppressWarnings, so this is suppressed at + // the method level.) + @SuppressWarnings("NullAway") public byte[] getBytes(int oneBasedPosition) throws SQLException { Object o = getObjectInternal(getZeroBasedPosition(oneBasedPosition)); if (o == null) { @@ -197,6 +202,11 @@ public Object getObject(int oneBasedPosition) throws SQLException { } @Override + // RelationalStruct#getString(int) (in the not-yet-migrated fdb-relational-api module) has no explicit + // @Nullable annotation, so NullAway treats it as @NonNull; this genuinely returns null for a SQL NULL column, + // same as before this migration. (A `return` statement can't itself carry @SuppressWarnings, so this is + // suppressed at the method level.) + @SuppressWarnings("NullAway") public String getString(int oneBasedPosition) throws SQLException { Object o = getObjectInternal(getZeroBasedPosition(oneBasedPosition)); if (o == null) { @@ -226,6 +236,11 @@ public String getString(String columnLabel) throws SQLException { } @Override + // RelationalStruct#getArray(int) (in the not-yet-migrated fdb-relational-api module) has no explicit @Nullable + // annotation, so NullAway treats it as @NonNull; this genuinely returns null for a SQL NULL column, same as + // before this migration. (A `return` statement can't itself carry @SuppressWarnings, so this is suppressed at + // the method level.) + @SuppressWarnings("NullAway") public RelationalArray getArray(int oneBasedPosition) throws SQLException { if (metaData.getColumnType(oneBasedPosition) != Types.ARRAY) { throw new SQLException("Array", ErrorCode.CANNOT_CONVERT_TYPE.getErrorCode()); @@ -278,6 +293,11 @@ public RelationalArray getArray(String columnLabel) throws SQLException { } @Override + // RelationalStruct#getStruct(int) (in the not-yet-migrated fdb-relational-api module) has no explicit + // @Nullable annotation, so NullAway treats it as @NonNull; this genuinely returns null for a SQL NULL column, + // same as before this migration. (A `return` statement can't itself carry @SuppressWarnings, so this is + // suppressed at the method level.) + @SuppressWarnings("NullAway") public RelationalStruct getStruct(int oneBasedColumn) throws SQLException { if (metaData.getColumnType(oneBasedColumn) != Types.STRUCT) { throw new SQLException("Struct", ErrorCode.CANNOT_CONVERT_TYPE.getErrorCode()); @@ -308,6 +328,11 @@ public UUID getUUID(String columnLabel) throws SQLException { } @Override + // RelationalStruct#getUUID(int) (in the not-yet-migrated fdb-relational-api module) has no explicit @Nullable + // annotation, so NullAway treats it as @NonNull; this genuinely returns null for a SQL NULL column, same as + // before this migration. (A `return` statement can't itself carry @SuppressWarnings, so this is suppressed at + // the method level.) + @SuppressWarnings("NullAway") public UUID getUUID(int oneBasedColumn) throws SQLException { if (metaData.getColumnType(oneBasedColumn) != Types.OTHER) { throw new SQLException("Expected UUID should have type OTHER", ErrorCode.CANNOT_CONVERT_TYPE.getErrorCode()); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/NoOpSchemaTemplateCatalog.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/NoOpSchemaTemplateCatalog.java index 626477bdf2c..748520a9dbf 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/NoOpSchemaTemplateCatalog.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/catalog/NoOpSchemaTemplateCatalog.java @@ -26,12 +26,16 @@ import com.apple.foundationdb.relational.api.Row; import com.apple.foundationdb.relational.api.Transaction; import com.apple.foundationdb.relational.api.RelationalResultSet; +import com.apple.foundationdb.relational.api.RelationalStructMetaData; +import com.apple.foundationdb.relational.api.metadata.DataType; import com.apple.foundationdb.relational.api.metadata.SchemaTemplate; import com.apple.foundationdb.relational.recordlayer.AbstractRecordLayerResultSet; import com.apple.foundationdb.relational.recordlayer.ContinuationImpl; import com.apple.foundationdb.relational.recordlayer.metadata.NoOpSchemaTemplate; import com.apple.foundationdb.relational.transactionbound.catalog.HollowSchemaTemplateCatalog; +import java.util.List; + /** * Implementation of Schema template catalog that ignores CRUD operations on templates. This is essentially used * to instantiate a store catalog object that ends up not caring about the schema template in the Schema. @@ -68,7 +72,9 @@ public SchemaTemplate loadSchemaTemplate(Transaction txn, String templateId, int @Override public RelationalResultSet listTemplates(Transaction txn) { - return new AbstractRecordLayerResultSet(null) { + // Previously constructed with a null StructMetaData; use a real (empty) one instead so + // getMetaData() below doesn't have to handle a null metaData field. + return new AbstractRecordLayerResultSet(RelationalStructMetaData.of(DataType.StructType.from("EMPTY", List.of(), false))) { @Override protected boolean hasNext() { return false; @@ -76,7 +82,10 @@ protected boolean hasNext() { @Override protected Row advanceRow() { - return null; + // hasNext() is hard-coded false above, so this is never actually called; returning null here + // would violate advanceRow()'s @NonNull contract, but changing that contract to accommodate + // this dead branch is out of scope here. + throw new IllegalStateException("advanceRow() should never be called: hasNext() is always false"); } @Override diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/DdlQuery.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/DdlQuery.java index 4e578a04486..70cc25ef2c7 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/DdlQuery.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/DdlQuery.java @@ -54,6 +54,7 @@ private NoOpDdlQuery() { } @Override + @SuppressWarnings("NullAway") // intentional no-op: this action never produces a result set to return. public RelationalResultSet executeAction(Transaction txn) throws RelationalException { return null; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/ProtobufDdlUtil.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/ProtobufDdlUtil.java index 32dcbad6355..dfadeab610b 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/ProtobufDdlUtil.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/ProtobufDdlUtil.java @@ -32,6 +32,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.TreeMap; import java.util.function.Function; import java.util.stream.Collectors; @@ -61,8 +62,10 @@ public static Type.Record recordFromDescriptor(Descriptors.Descriptor descriptor } else if (o2 == null) { return 1; } else { - Descriptors.FieldDescriptor field1 = descriptorLookupMap.get(o1); - Descriptors.FieldDescriptor field2 = descriptorLookupMap.get(o2); + // Both o1 and o2 are always keys of descriptorLookupMap: this comparator is only ever + // invoked (via orderedFieldMap.putAll below) on keys drawn from that same map. + Descriptors.FieldDescriptor field1 = Objects.requireNonNull(descriptorLookupMap.get(o1)); + Descriptors.FieldDescriptor field2 = Objects.requireNonNull(descriptorLookupMap.get(o2)); return Integer.compare(field1.getIndex(), field2.getIndex()); } }); @@ -189,8 +192,10 @@ public static Type.Record recordFromFieldDescriptors(List T clock(RelationalMetric.RelationalEvent event, Supplier supplier) throws RelationalException; + T clock(RelationalMetric.RelationalEvent event, Supplier supplier) throws RelationalException; /** * Returns the aggregate time taken by all the occurrences of a particular event in the lifetime of collector. diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/options/package-info.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/options/package-info.java index 7863ccd35d7..189b33f3c68 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/options/package-info.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/options/package-info.java @@ -21,4 +21,7 @@ /** * Interfaces and core API functions around implementing a Catalog instance. */ +@NullMarked package com.apple.foundationdb.relational.api.options; + +import org.jspecify.annotations.NullMarked; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/AbstractDatabase.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/AbstractDatabase.java index 1b4d1933cb5..492c9abeb36 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/AbstractDatabase.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/AbstractDatabase.java @@ -37,6 +37,7 @@ import java.sql.SQLException; import java.util.HashMap; import java.util.Map; +import java.util.Objects; public abstract class AbstractDatabase implements RelationalDatabase { @@ -79,7 +80,9 @@ public RecordLayerSchema loadSchema(String schemaId) throws RelationalException if (schema == null) { // The SchemaExistenceCheck from the options is only taken when the schema is created firstly // It is an immutable parameter for the schema and the options for the following operations on that schema are ignored - schema = new RecordLayerSchema(schemaId, this, connection); + // connection is set via setConnection(...) as part of database construction, before any + // schema is ever loaded, so it is always present by the time loadSchema() is called. + schema = new RecordLayerSchema(schemaId, this, Objects.requireNonNull(connection, "connection not set on database before loadSchema() was called")); putBack = true; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/AbstractEmbeddedStatement.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/AbstractEmbeddedStatement.java index 03be6817061..afe2322f1eb 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/AbstractEmbeddedStatement.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/AbstractEmbeddedStatement.java @@ -70,6 +70,11 @@ public boolean executeInternal(String sql) throws SQLException, RelationalExcept checkOpen(); Assert.notNull(sql); conn.ensureTransactionActive(); + // conn.getMetricCollector() is @Nullable only because the collector isn't set up until a + // transaction is active (just above); Assert.notNullUnchecked enforces that invariant at + // runtime with a clear RelationalException, but NullAway can't see that since Assert lives in + // the not-yet-migrated fdb-relational-api module. + @SuppressWarnings("NullAway") final var metricCollector = Assert.notNullUnchecked(conn.getMetricCollector()); return metricCollector.clock(RelationalMetric.RelationalEvent.TOTAL_PROCESS_QUERY, () -> { try { @@ -106,6 +111,8 @@ public boolean executeInternal(String sql) throws SQLException, RelationalExcept } private boolean clockAndExecuteQueryPlan(final QueryPlan plan, final Plan.ExecutionContext executionContext) throws RelationalException { + // See the comment on the analogous call in executeInternal() above for why this is suppressed. + @SuppressWarnings("NullAway") final var metricCollector = Assert.notNullUnchecked(conn.getMetricCollector()); return metricCollector.clock(RelationalMetric.RelationalEvent.EXECUTE_QUERY_PLAN, () -> { currentResultSet = new ErrorCapturingResultSet(plan.execute(executionContext)); @@ -129,6 +136,8 @@ private boolean clockAndExecuteQueryPlan(final QueryPlan plan, final Plan.Execut } private boolean clockAndExecuteNonQueryPlan(final Plan plan, final Plan.ExecutionContext executionContext) throws RelationalException { + // See the comment on the analogous call in executeInternal() above for why this is suppressed. + @SuppressWarnings("NullAway") final var metricCollector = Assert.notNullUnchecked(conn.getMetricCollector()); return metricCollector.clock(RelationalMetric.RelationalEvent.EXECUTE_NON_QUERY_PLAN, () -> { plan.execute(executionContext); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/CatalogMetaData.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/CatalogMetaData.java index 5ebfc756ebb..a17b22c220d 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/CatalogMetaData.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/CatalogMetaData.java @@ -44,6 +44,7 @@ import com.apple.foundationdb.relational.util.Assert; import com.google.protobuf.Descriptors; +import org.jspecify.annotations.Nullable; import java.net.URI; import java.sql.DatabaseMetaData; import java.sql.SQLException; @@ -75,7 +76,9 @@ public RelationalResultSet getSchemas() throws SQLException { } @Override - public RelationalResultSet getSchemas(String catalogStr, String schemaPattern) throws SQLException { + // Both params mirror java.sql.DatabaseMetaData#getSchemas(String, String), which documents both as + // nullable ("null means..."); catalogStr is already null-checked below, and schemaPattern isn't used. + public RelationalResultSet getSchemas(@Nullable String catalogStr, @Nullable String schemaPattern) throws SQLException { if (catalogStr == null) { throw new OperationUnsupportedException("Must use a non-null catalog name currently").toSqlException(); } @@ -153,12 +156,7 @@ public RelationalResultSet getPrimaryKeys(String database, String schema, String RecordKeyExpressionProto.KeyExpression ke = type.getPrimaryKey(); return new AbstractMap.SimpleEntry<>(type.getName(), keyExpressionToPrimaryKey(ke)); }).flatMap(pks -> IntStream.range(0, pks.getValue().length) - .mapToObj(pos -> new ArrayRow(database, - schema, - pks.getKey(), - pks.getValue()[pos], - pos + 1, - null))); + .mapToObj(pos -> newPrimaryKeyRow(database, schema, pks.getKey(), pks.getValue()[pos], pos + 1))); final var primaryKeysStructType = DataType.StructType.from("PRIMARY_KEYS", List.of( DataType.StructType.Field.from("TABLE_CAT", DataType.Primitives.NULLABLE_STRING.type(), 0), @@ -334,6 +332,14 @@ public RelationalResultSet getIndexInfo(String database, String schema, String t }); } + // ArrayRow's vararg parameter type isn't @Nullable (NullAway/JSpecify doesn't reliably track element + // nullability for array/vararg-typed parameters); PK_NAME (the last column) is genuinely null here, + // matching java.sql.DatabaseMetaData#getPrimaryKeys()'s documented, always-nullable PK_NAME column. + @SuppressWarnings("NullAway") + private static ArrayRow newPrimaryKeyRow(String database, String schema, String tableName, String columnName, int keySeq) { + return new ArrayRow(database, schema, tableName, columnName, keySeq, null); + } + private RecordMetaDataProto.MetaData loadSchemaMetadata(final String database, final String schema) throws RelationalException { final var recLayerSchema = this.catalog.loadSchema(conn.getTransaction(), URI.create(database), schema); Assert.thatUnchecked(recLayerSchema instanceof RecordLayerSchema); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ContinuationImpl.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ContinuationImpl.java index 55177a83b10..d0fa8dd62c8 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ContinuationImpl.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ContinuationImpl.java @@ -42,6 +42,10 @@ public final class ContinuationImpl implements Continuation { public static final int CURRENT_VERSION = 1; + // NullAway/JSpecify does not reliably track @Nullable on byte[] parameters across this constructor call; this + // genuinely passes null to represent "no continuation bytes" for the BEGIN sentinel, same as before this + // migration. + @SuppressWarnings("NullAway") public static final ContinuationImpl BEGIN = new ContinuationImpl((byte[]) null); public static final ContinuationImpl END = new ContinuationImpl(new byte[0]); @@ -72,6 +76,11 @@ public byte[] serialize() { @Nullable @Override + // Continuation#getExecutionState() is declared @Nullable byte[] (using javax.annotation.Nullable in the + // not-yet-migrated fdb-relational-api module), but NullAway/JSpecify does not reliably match array-typed + // nullability across that annotation boundary, so this override is flagged as mismatched even though it + // genuinely returns null when there is no execution state, same as before this migration. + @SuppressWarnings("NullAway") public byte[] getExecutionState() { if (!proto.hasExecutionState()) { return null; @@ -81,6 +90,10 @@ public byte[] getExecutionState() { } @Override + // Continuation#getReason() (in the not-yet-migrated fdb-relational-api module) has no explicit @Nullable + // annotation, so NullAway treats it as @NonNull; this override genuinely returns null when the proto has no + // reason set, same as before this migration. + @SuppressWarnings("NullAway") public Reason getReason() { if (proto.hasReason()) { return Reason.valueOf(proto.getReason().name()); @@ -179,6 +192,10 @@ public static Continuation fromInt(int offset) { * @param cursorContinuation the inner cursor continuation to be placed inside the newly created continuation * @return a continuation that holds the given cursor continuation */ + // RecordCursorContinuation#toBytes() is declared @Nullable (javax.annotation.Nullable, in the unmigrated + // fdb-record-layer-core module); NullAway/JSpecify does not reliably track @Nullable on byte[] return values + // across that boundary, though the ContinuationImpl constructor genuinely accepts null here. + @SuppressWarnings("NullAway") public static Continuation fromRecordCursorContinuation(RecordCursorContinuation cursorContinuation) { return cursorContinuation.isEnd() ? END : new ContinuationImpl(cursorContinuation.toBytes()); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/DirectScannable.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/DirectScannable.java index 97f416bc4a6..f659fe68243 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/DirectScannable.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/DirectScannable.java @@ -53,6 +53,12 @@ ResumableIterator openScan( @Nullable Row keyPrefix, Options options) throws RelationalException; + /** + * Get the record at the given key. + * + * @return the row at the given key, or {@code null} if no such row exists. + */ + @Nullable Row get(Transaction t, Row key, Options options) throws RelationalException; KeyBuilder getKeyBuilder() throws RelationalException; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalConnection.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalConnection.java index a1e037d5d0a..1adf780948d 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalConnection.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalConnection.java @@ -62,6 +62,7 @@ import java.sql.Struct; import java.util.Arrays; import java.util.Locale; +import java.util.Objects; import java.util.stream.Collectors; /** @@ -95,6 +96,9 @@ public class EmbeddedRelationalConnection implements RelationalConnection { @Nullable private Transaction transaction; ExecuteProperties executeProperties; + // No schema has been selected yet until setSchema()/setSchema(schema, ...) is called; getSchema() below + // legitimately returns null in that state, matching java.sql.Connection#getSchema()'s contract. + @Nullable private String currentSchemaLabel; private boolean autoCommit = true; private final boolean usingAnExternalTransaction; @@ -113,7 +117,7 @@ public EmbeddedRelationalConnection(AbstractDatabase frl, this.txnManager = frl.getTransactionManager(); this.transaction = transaction; this.usingAnExternalTransaction = transaction != null; - if (usingAnExternalTransaction) { + if (transaction != null) { this.metricCollector = StoreTimerMetricCollector.fromFDBRecordContext(transaction.unwrap(RecordContextTransaction.class).getContext()); } this.backingCatalog = backingCatalog; @@ -258,13 +262,19 @@ private void checkSchemaExists(String schema) throws SQLException { if (!this.backingCatalog.doesSchemaExist(getTransaction(), getRecordLayerDatabase().getURI(), schema)) { throw new RelationalException(String.format(Locale.ROOT, "Schema %s does not exist in %s", schema, getPath()), ErrorCode.UNDEFINED_SCHEMA); } - return null; + // Return value is unused by this caller; runIsolatedInTransactionIfPossible's Supplier requires a + // non-null result. + return Boolean.TRUE; }); } public SchemaTemplate getSchemaTemplate() throws RelationalException { try { - return backingCatalog.loadSchema(getTransaction(), getPath(), getSchema()).getSchemaTemplate(); + final String schema = getSchema(); + if (schema == null) { + throw new RelationalException("No Schema specified", ErrorCode.UNDEFINED_SCHEMA); + } + return backingCatalog.loadSchema(getTransaction(), getPath(), schema).getSchemaTemplate(); } catch (SQLException sqle) { throw new RelationalException(sqle); } @@ -276,6 +286,7 @@ public MetricCollector getMetricCollector() { } @Override + @Nullable public String getSchema() throws SQLException { checkOpen(); return currentSchemaLabel; @@ -347,6 +358,10 @@ public int getTransactionIsolation() throws SQLException { } @Override + // RelationalConnection#getWarnings() (default method in the not-yet-migrated fdb-relational-api module) has no + // explicit @Nullable annotation, so NullAway treats it as @NonNull; this override genuinely returns null + // (warnings are not implemented yet), matching java.sql.Connection#getWarnings()'s real, nullable contract. + @SuppressWarnings("NullAway") public SQLWarning getWarnings() throws SQLException { // Return null for now until we implement Warnings. Returning an exception breaks processing. return null; @@ -447,7 +462,7 @@ boolean inActiveTransaction() { } void addCloseListener(Runnable closeListener) throws RelationalException { - this.transaction.unwrap(RecordContextTransaction.class).addTerminationListener(closeListener); + getTransaction().unwrap(RecordContextTransaction.class).addTerminationListener(closeListener); } public AbstractDatabase getRecordLayerDatabase() { @@ -572,7 +587,10 @@ T runIsolatedInTransactionIfPossible(Supplier operation) throws SQLExcept if (exception != null) { throw exception; } else { - return result; + // If we reach here, the try block above completed without catching a RelationalException, so + // operation.get() ran to completion and assigned a real result; NullAway can't correlate that with + // the null-check on the unrelated `exception` variable. + return Objects.requireNonNull(result, "operation completed without an exception, so it must have produced a result"); } } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalPreparedStatement.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalPreparedStatement.java index 3980053af8a..3b66d7b72c2 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalPreparedStatement.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalPreparedStatement.java @@ -37,6 +37,7 @@ import java.sql.SQLException; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.TreeMap; import java.util.UUID; @@ -55,7 +56,9 @@ public EmbeddedRelationalPreparedStatement(String sql, EmbeddedRelationalConnect public RelationalResultSet executeQuery() throws SQLException { checkOpen(); if (execute()) { - return currentResultSet; + // execute() returning true (per AbstractEmbeddedStatement#clockAndExecuteQueryPlan) is exactly + // what guarantees currentResultSet is set at this point. + return Objects.requireNonNull(currentResultSet); } else { throw new SQLException(String.format(Locale.ROOT, "query '%s' does not return result set, use JDBC executeUpdate method instead", sql), ErrorCode.NO_RESULT_SET.getErrorCode()); } @@ -212,6 +215,11 @@ public void setNull(String parameterName, int sqlType) throws SQLException { } @Override + // conn.getMetricCollector() is @Nullable only because the collector isn't set up until a transaction + // is active; Assert.notNullUnchecked enforces that invariant at runtime with a clear + // RelationalException, but NullAway can't see that since Assert lives in the not-yet-migrated + // fdb-relational-api module. + @SuppressWarnings("NullAway") PlanContext createPlanContext(final FDBRecordStoreBase store, final Options options) throws RelationalException { return PlanContext.builder() .fromRecordStore(store, options) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalStatement.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalStatement.java index 17e04b135f8..13920afa1e3 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalStatement.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalStatement.java @@ -46,6 +46,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Set; @API(API.Status.EXPERIMENTAL) @@ -56,6 +57,11 @@ public EmbeddedRelationalStatement(EmbeddedRelationalConnection conn) throws SQL } @Override + // conn.getMetricCollector() is @Nullable only because the collector isn't set up until a transaction + // is active; Assert.notNullUnchecked enforces that invariant at runtime with a clear + // RelationalException, but NullAway can't see that since Assert lives in the not-yet-migrated + // fdb-relational-api module. + @SuppressWarnings("NullAway") PlanContext createPlanContext(final FDBRecordStoreBase store, final Options options) throws RelationalException { return PlanContext.builder() .fromRecordStore(store, options) @@ -232,7 +238,9 @@ public void executeDeleteRange(String tableName, KeySet prefix, Options options) if (row.getObject(keyLength - 1) != null) { // We have a complete key. Delete only the one record table.deleteRecord(row); - return null; + // Return value is unused by executeDeleteRange; ensureTransaction's Supplier requires a + // non-null result. + return Boolean.TRUE; } } try { @@ -258,7 +266,9 @@ public void executeDeleteRange(String tableName, KeySet prefix, Options options) throw new RuntimeException(sqle); } } - return null; + // Return value is unused by executeDeleteRange; ensureTransaction's Supplier requires a non-null + // result. + return Boolean.TRUE; }); } @@ -338,7 +348,10 @@ private T ensureTransaction(Supplier operation) throws SQLException { if (exception != null) { throw exception; } else { - return result; + // If we reach here, the try block above completed without catching an exception, so operation.get() + // ran to completion and assigned a real result; NullAway can't correlate that with the null-check on + // the unrelated `exception` variable. + return Objects.requireNonNull(result, "operation completed without an exception, so it must have produced a result"); } } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/IteratorResultSet.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/IteratorResultSet.java index 0e15223cbfe..d48a03eda40 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/IteratorResultSet.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/IteratorResultSet.java @@ -82,6 +82,12 @@ protected boolean hasNext() { } @Override + // advanceRow() genuinely returns null once the underlying iterator is exhausted; the caller, + // AbstractRecordLayerResultSet#next(), checks the result for null immediately after calling this. The + // inherited method signature (in AbstractRecordLayerResultSet, outside this migration's scope) still declares + // a @NonNull return type, and a `return` statement can't itself carry @SuppressWarnings, so this is suppressed + // at the method level. + @SuppressWarnings("NullAway") protected Row advanceRow() throws RelationalException { if (!rowIter.hasNext()) { return null; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/KeySpaceUtils.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/KeySpaceUtils.java index a58b926e908..d8c0d47664d 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/KeySpaceUtils.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/KeySpaceUtils.java @@ -55,7 +55,8 @@ private static List pathToUriList(final KeySpacePath dbPath) { private static String toPathElement(final KeySpacePath path) { if (path.getDirectory().getKeyType() != KeySpaceDirectory.KeyType.NULL) { - return path.getValue().toString(); + // The KeyType.NULL check above is precisely what guarantees getValue() is non-null here. + return Objects.requireNonNull(path.getValue()).toString(); } else { return ""; } @@ -244,7 +245,7 @@ private static Object getConstantValue(final KeySpaceDirectory directory) throws } @Nullable - private static KeySpacePath getSubPath(final KeySpace keySpace, final @Nullable KeySpacePath parentPath, final String pathName, final Object pathValue) { + private static KeySpacePath getSubPath(final KeySpace keySpace, final @Nullable KeySpacePath parentPath, final String pathName, final @Nullable Object pathValue) { try { if (parentPath == null) { return keySpace.path(pathName, pathValue); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/MessageTuple.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/MessageTuple.java index f9f9e109486..1d4e8d28ed7 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/MessageTuple.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/MessageTuple.java @@ -32,6 +32,7 @@ import com.google.protobuf.Descriptors; import com.google.protobuf.Message; +import org.jspecify.annotations.Nullable; import java.util.List; import java.util.stream.Collectors; @@ -49,6 +50,7 @@ public int getNumFields() { } @Override + @Nullable public Object getObject(int position) throws InvalidColumnReferenceException { if (position < 0 || position >= getNumFields()) { throw InvalidColumnReferenceException.getExceptionForInvalidPositionNumber(position); @@ -76,6 +78,7 @@ public Object getObject(int position) throws InvalidColumnReferenceException { } } + @Nullable public static Object sanitizeField(final Object field, final DescriptorProtos.FieldOptions fieldOptions) { if (field instanceof Message && ((Message) field).getDescriptorForType().equals(TupleFieldsProto.UUID.getDescriptor())) { return TupleFieldsHelper.fromProto((Message) field, TupleFieldsProto.UUID.getDescriptor()); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/QueryExecutor.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/QueryExecutor.java index d137aedb549..a6c8a0c0628 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/QueryExecutor.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/QueryExecutor.java @@ -64,6 +64,7 @@ public ResumableIterator execute(@Nullable final Continuation continuation, return RecordLayerIterator.create(cursor, messageFDBQueriedRecord -> new MessageTuple(messageFDBQueriedRecord.getMessage())); } + @Nullable public Type getQueryResultType() { return plan.getResultType().getInnerType(); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordContextTransaction.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordContextTransaction.java index ed40f74c12f..c76169caa20 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordContextTransaction.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordContextTransaction.java @@ -35,6 +35,7 @@ import java.util.LinkedList; import java.util.List; +import java.util.Objects; import java.util.Optional; /** @@ -64,7 +65,7 @@ public void commit() throws RelationalException { try { context.commit(); } catch (FDBExceptions.FDBStoreTransactionConflictException ex) { - throw new RelationalException(ex.getMessage(), ErrorCode.SERIALIZATION_FAILURE, ex); + throw new RelationalException(Objects.requireNonNullElse(ex.getMessage(), ex.toString()), ErrorCode.SERIALIZATION_FAILURE, ex); } catch (RecordCoreException e) { throw ExceptionUtil.toRelationalException(e); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerIterator.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerIterator.java index 2f563dc674e..beae5b6569d 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerIterator.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerIterator.java @@ -32,15 +32,22 @@ import com.apple.foundationdb.relational.recordlayer.util.ExceptionUtil; import org.jspecify.annotations.Nullable; +import java.util.Objects; import java.util.function.Function; @API(API.Status.EXPERIMENTAL) public final class RecordLayerIterator implements ResumableIterator { private final RecordCursor recordCursor; private final Function transform; + // null until the first fetchNextResult() call, and again briefly at the very start of next() (see the + // "result = null" reset in its finally block, immediately followed by the next hasNext()/fetchNextResult() + // re-populating it). + @Nullable private RecordCursorResult result; private Continuation continuation; - private RecordCursor.NoNextReason noNextReason = null; + // null until iteration is exhausted; see fetchNextResult() and getNoNextReason() below. + @Nullable + private RecordCursor.NoNextReason noNextReason; private RecordLayerIterator(RecordCursor cursor, Function transform) throws RelationalException { this.recordCursor = cursor; @@ -76,23 +83,35 @@ public Continuation getContinuation() throws RelationalException { @Override public boolean hasNext() { - fetchNextResult(); - return result.hasNext(); + return fetchNextResult().hasNext(); } - private void fetchNextResult() { - if (result != null) { - return; + // Returns the current (always non-null) fetched result, populating it (and, if iteration has ended, + // noNextReason/continuation) first if necessary. Every other method in this class that needs the + // current result goes through this method rather than reading the result field directly, so that + // NullAway sees the narrowing. + private RecordCursorResult fetchNextResult() { + RecordCursorResult currentResult = result; + if (currentResult != null) { + return currentResult; } - result = recordCursor.getNext(); - if (!result.hasNext()) { - noNextReason = result.getNoNextReason(); - if (noNextReason == RecordCursor.NoNextReason.SOURCE_EXHAUSTED) { + currentResult = recordCursor.getNext(); + result = currentResult; + if (!currentResult.hasNext()) { + final RecordCursor.NoNextReason reason = currentResult.getNoNextReason(); + noNextReason = reason; + if (reason == RecordCursor.NoNextReason.SOURCE_EXHAUSTED) { this.continuation = ContinuationImpl.END; } else { - this.continuation = ContinuationImpl.fromUnderlyingBytes(result.getContinuation().toBytes()); + // NullAway/JSpecify does not reliably track @Nullable on array-typed (byte[]) parameters: + // fromUnderlyingBytes(@Nullable byte[]) already accepts null, and toBytes() genuinely + // returns null in some cases (see RecordCursorContinuation#toBytes() javadoc). + @SuppressWarnings("NullAway") + final Continuation cont = ContinuationImpl.fromUnderlyingBytes(currentResult.getContinuation().toBytes()); + this.continuation = cont; } } + return currentResult; } @Override @@ -101,9 +120,16 @@ public Row next() { if (hasNext()) { // The current RecordCursorResult has a value to be returned to the consumer. try { - final var row = transform.apply(result.get()); + final RecordCursorResult currentResult = fetchNextResult(); + // hasNext() above (via fetchNextResult().hasNext()) is what guarantees get() is non-null here. + @SuppressWarnings("NullAway") + final T nextValue = currentResult.get(); + final var row = transform.apply(nextValue); // TODO(sfines,yhatem) pass the Record-Layer Continuation object as-is to avoid copying bytes around. - this.continuation = ContinuationImpl.fromUnderlyingBytes(result.getContinuation().toBytes()); + // See the comment in fetchNextResult() above about this same @SuppressWarnings. + @SuppressWarnings("NullAway") + final Continuation cont = ContinuationImpl.fromUnderlyingBytes(currentResult.getContinuation().toBytes()); + this.continuation = cont; return row; } catch (RecordCoreException exception) { throw ExceptionUtil.toRelationalException(exception).toUncheckedWrappedException(); @@ -112,7 +138,8 @@ public Row next() { result = null; } } else if (terminatedEarly()) { - throw new RelationalException(terminatedEarlyReason(), ErrorCode.EXECUTION_LIMIT_REACHED).toUncheckedWrappedException(); + // terminatedEarly() (just checked true) is what guarantees terminatedEarlyReason() is non-null here. + throw new RelationalException(Objects.requireNonNull(terminatedEarlyReason()), ErrorCode.EXECUTION_LIMIT_REACHED).toUncheckedWrappedException(); } else { throw new RelationalException("No next row available", ErrorCode.INVALID_CURSOR_STATE).toUncheckedWrappedException(); } @@ -128,7 +155,9 @@ public boolean terminatedEarly() { @Override public RecordCursor.NoNextReason getNoNextReason() { - return noNextReason; + // Only meaningful (and only ever called) once iteration has ended, at which point fetchNextResult() + // has already set noNextReason; see terminatedEarly() and RecordLayerResultSet's caller. + return Objects.requireNonNull(noNextReason, "getNoNextReason() called before iteration ended"); } @Nullable @@ -136,7 +165,7 @@ private String terminatedEarlyReason() { if (!terminatedEarly()) { return null; } - switch (noNextReason) { + switch (Objects.requireNonNull(noNextReason)) { case TIME_LIMIT_REACHED: return "Time Limit allowed for the current transaction is exhausted"; case BYTE_LIMIT_REACHED: diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerResultSet.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerResultSet.java index f559af26b8b..af4dbf2b02c 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerResultSet.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerResultSet.java @@ -43,6 +43,9 @@ public class RecordLayerResultSet extends AbstractRecordLayerResultSet { @Nullable private final EmbeddedRelationalConnection connection; + // null until the first call to advanceRow(), and again whenever the underlying cursor is exhausted; see + // advanceRow() below. + @Nullable private Row currentRow; private volatile boolean closed; @@ -71,7 +74,13 @@ protected boolean hasNext() { } @Override - @SuppressWarnings("PMD.PreserveStackTrace") + @SuppressWarnings({"PMD.PreserveStackTrace", + // advanceRow() genuinely returns null once the underlying cursor is exhausted; the caller, + // AbstractRecordLayerResultSet#next(), checks the result for null immediately after calling this. The + // inherited method signature (in AbstractRecordLayerResultSet, outside this migration's scope) still + // declares a @NonNull return type, and a `return` statement can't itself carry @SuppressWarnings, so + // this is suppressed at the method level. + "NullAway"}) protected Row advanceRow() throws RelationalException { currentRow = null; if (currentCursor.hasNext()) { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerSchema.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerSchema.java index 8f7aa884287..238bf8af960 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerSchema.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerSchema.java @@ -31,6 +31,7 @@ import com.apple.foundationdb.relational.util.Assert; import javax.annotation.concurrent.NotThreadSafe; +import org.jspecify.annotations.Nullable; import java.util.HashMap; import java.util.Map; @@ -46,6 +47,7 @@ public class RecordLayerSchema implements DatabaseSchema { private final FDBRecordStoreBase.StoreExistenceCheck existenceCheck; //TODO(bfines) destroy this when the connection's transaction ends + @Nullable private BackingStore currentStore; /* diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerStorageCluster.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerStorageCluster.java index 01b74d307d9..37528dde396 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerStorageCluster.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerStorageCluster.java @@ -61,7 +61,7 @@ public RecordLayerStorageCluster(FdbConnection connection, KeySpace keySpace, RecordLayerConfig rlConfig, StoreCatalog storeCatalog, - RelationalPlanCache planCache, + @Nullable RelationalPlanCache planCache, RecordLayerMetadataOperationsFactory ddlFactory) { //TODO(bfines) we shouldn't use FDBStoreTimer, we should use our own abstraction that can be easily disabled this.fdb = connection; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordStoreIndex.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordStoreIndex.java index 597eedbb84a..10927d57ade 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordStoreIndex.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordStoreIndex.java @@ -86,6 +86,7 @@ public void close() throws RelationalException { } @Override + @Nullable public Row get(Transaction t, Row key, Options options) throws RelationalException { BackingStore store = getSchema().loadStore(); return store.getFromIndex(index, key, options); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordTypeScannable.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordTypeScannable.java index 6f6cfeb9a6f..a1b0c1b6b96 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordTypeScannable.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordTypeScannable.java @@ -38,7 +38,10 @@ public abstract class RecordTypeScannable implements DirectScannable { public final ResumableIterator openScan( @Nullable Row keyPrefix, Options options) throws RelationalException { - TupleRange range = TupleRange.allOf(TupleUtils.toFDBTuple(keyPrefix)); + // A null keyPrefix means "no prefix restriction" (a full scan), which TupleRange.allOf already + // supports directly with a null Tuple; TupleUtils.toFDBTuple itself does not accept null, so it + // must only be called once we know keyPrefix is present. + TupleRange range = TupleRange.allOf(keyPrefix == null ? null : TupleUtils.toFDBTuple(keyPrefix)); BackingStore store = getSchema().loadStore(); final RecordCursor cursor = openScan(store, range, options.getOption(Options.Name.CONTINUATION), options); return RecordLayerIterator.create(cursor, keyValueTransform()); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordTypeTable.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordTypeTable.java index e2a6d2f7a6d..65260dad844 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordTypeTable.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordTypeTable.java @@ -62,6 +62,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.TreeMap; @@ -77,6 +78,7 @@ public class RecordTypeTable extends RecordTypeScannable currentTypeRef = null); } catch (MetaDataException mde) { - throw new RelationalException(mde.getMessage(), ErrorCode.UNDEFINED_SCHEMA, mde); + throw new RelationalException(Objects.requireNonNullElse(mde.getMessage(), mde.toString()), ErrorCode.UNDEFINED_SCHEMA, mde); } } else { //make sure that this record type is valid _for the operation we are doing now_. diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/CatalogMetaDataProvider.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/CatalogMetaDataProvider.java index 67628483d47..fcfef1667da 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/CatalogMetaDataProvider.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/CatalogMetaDataProvider.java @@ -33,6 +33,7 @@ import com.apple.foundationdb.relational.recordlayer.metadata.RecordLayerSchemaTemplate; import com.apple.foundationdb.relational.util.Assert; +import org.jspecify.annotations.Nullable; import java.net.URI; @API(API.Status.EXPERIMENTAL) @@ -44,6 +45,8 @@ public class CatalogMetaDataProvider implements RecordMetaDataProvider { private final String schemaName; private final Transaction txn; + // Lazily computed and cached on first getRecordMetaData() call; null until then. + @Nullable private volatile RecordMetaData cachedMetaData; public CatalogMetaDataProvider(StoreCatalog storeCatalog, diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalog.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalog.java index 832486e7b2c..2b94ea7f39f 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalog.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalog.java @@ -129,6 +129,9 @@ class RecordLayerStoreCatalog implements StoreCatalog, KeySpaceProvider { private final RecordLayerSchema catalogSchema; @SpotBugsSuppressWarnings(value = "CT_CONSTRUCTOR_THROW", justification = "Hard to remove exception with current inheritance") + // schemaTemplateCatalog is populated by initialize(), which the class Javadoc requires to be + // called before the catalog can be used; NullAway cannot see this two-phase initialization. + @SuppressWarnings("NullAway.Init") RecordLayerStoreCatalog(final KeySpace keySpace) throws RelationalException { this.keySpace = keySpace; this.catalogSchemaPath = RelationalKeyspaceProvider.toDatabasePath(DASH_DASH_SYS, keySpace) @@ -453,11 +456,7 @@ private Tuple getSchemaKey(URI databaseId, String schemaName) { return Tuple.from(SystemTableRegistry.SCHEMA_RECORD_TYPE_KEY, databaseId.getPath(), schemaName); } - @Nullable - private Row transformSchema(@Nullable FDBStoredRecord record) { - if (record == null) { - return null; - } + private Row transformSchema(FDBStoredRecord record) { Message m = record.getRecord(); final RecordMetaData recordMetaData = catalogRecordMetaDataProvider.getRecordMetaData(); final RecordType schemaTableMD = recordMetaData.getRecordType(SystemTableRegistry.SCHEMAS_TABLE_NAME); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreSchemaTemplateCatalog.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreSchemaTemplateCatalog.java index 126c083200c..dbd23a8f023 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreSchemaTemplateCatalog.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreSchemaTemplateCatalog.java @@ -178,7 +178,12 @@ public SchemaTemplate loadSchemaTemplate(final Transaction txn, final String tem final var schemaExists = !cursorResult.getContinuation().isEnd() && cursorResult.get() != null; Assert.thatUnchecked(schemaExists, ErrorCode.UNKNOWN_SCHEMA_TEMPLATE, "SchemaTemplate '" + templateName + "' is not in catalog"); - return toSchemaTemplate(Assert.notNullUnchecked(cursorResult.get()).getRecord()); + // schemaExists (just asserted true above) already established that cursorResult.get() != null; + // NullAway can't track that across the Assert.thatUnchecked call since Assert lives in the + // not-yet-migrated fdb-relational-api module. + @SuppressWarnings("NullAway") + final var record = Assert.notNullUnchecked(cursorResult.get()).getRecord(); + return toSchemaTemplate(record); } catch (RecordCoreStorageException | InvalidProtocolBufferException e) { throw new UncheckedRelationalException(ExceptionUtil.toRelationalException(e)); } @@ -260,6 +265,11 @@ public RelationalResultSet listTemplates(Transaction txn) { } } + // Defensive: the scanRecords() cursor above never actually yields a null element, so the null branch + // below is not expected to be hit; returning null there would violate this method's Function + // contract (RecordLayerIterator#next() forwards it without a null check), but changing that contract to + // accommodate this dead branch is out of scope here. + @SuppressWarnings("NullAway") private Row transformSchemaTemplates(@Nullable FDBStoredRecord record) { if (record == null) { return null; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/TransactionBoundDatabase.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/TransactionBoundDatabase.java index bdedad448c4..2c947aac415 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/TransactionBoundDatabase.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/TransactionBoundDatabase.java @@ -48,6 +48,7 @@ import org.jspecify.annotations.Nullable; import java.net.URI; +import java.util.Objects; /** * There can only be 1 Database object per Connection instance, and its lifecycle is managed by the connection @@ -64,6 +65,8 @@ public class TransactionBoundDatabase extends AbstractDatabase { @Nullable private final KeySpace keySpace; + // store is only populated once connect() is called; it is not available beforehand. + @Nullable BackingStore store; URI uri; @@ -103,7 +106,7 @@ public RelationalConnection connect(@Nullable Transaction transaction) throws Re @Override public BackingStore loadRecordStore(String schemaId, FDBRecordStoreBase.StoreExistenceCheck existenceCheck) { - return store; + return Objects.requireNonNull(store, "loadRecordStore() called before connect()"); } @Override diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/DropDatabaseConstantAction.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/DropDatabaseConstantAction.java index 0dc3258dd49..28e33834fde 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/DropDatabaseConstantAction.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/DropDatabaseConstantAction.java @@ -34,6 +34,7 @@ import java.net.URI; import java.sql.SQLException; +import java.util.Objects; @API(API.Status.EXPERIMENTAL) public class DropDatabaseConstantAction implements ConstantAction { @@ -67,7 +68,7 @@ public void execute(Transaction txn) throws RelationalException { } } catch (SQLException se) { ErrorCode ec = ErrorCode.get(se.getSQLState()); - throw new RelationalException(se.getMessage(), ec, se); + throw new RelationalException(Objects.requireNonNullElse(se.getMessage(), se.toString()), ec, se); } catalog.deleteDatabase(txn, dbUrl, throwIfDoesNotExist); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/RecordLayerMetadataOperationsFactory.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/RecordLayerMetadataOperationsFactory.java index fbabef14db7..89b746e9cd4 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/RecordLayerMetadataOperationsFactory.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/RecordLayerMetadataOperationsFactory.java @@ -99,6 +99,12 @@ public static class Builder { protected RecordLayerConfig rlConfig; protected KeySpace baseKeySpace; + // storeCatalog, rlConfig, and baseKeySpace are populated by the fluent setters below, so + // NullAway cannot see that they are always set before use in build(). + @SuppressWarnings("NullAway.Init") + public Builder() { + } + public Builder setStoreCatalog(StoreCatalog storeCatalog) { this.storeCatalog = storeCatalog; return this; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/DataTypeUtils.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/DataTypeUtils.java index cbcad28b4b1..816b91f7e4c 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/DataTypeUtils.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/DataTypeUtils.java @@ -25,12 +25,12 @@ import com.apple.foundationdb.record.util.ProtoUtils; import com.apple.foundationdb.relational.api.metadata.DataType; import com.apple.foundationdb.relational.util.Assert; -import com.apple.foundationdb.relational.util.SpotBugsSuppressWarnings; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import java.util.List; import java.util.Locale; +import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; @@ -49,7 +49,9 @@ public class DataTypeUtils { */ public static DataType toRelationalType(final Type type) { if (primitivesMap.containsValue(type)) { - return primitivesMap.inverse().get(type); + // primitivesMap.inverse() is a view over the same entries with keys/values swapped, + // so containsValue(type) on the original map guarantees inverse().get(type) hits. + return Objects.requireNonNull(primitivesMap.inverse().get(type)); } final var typeCode = type.getTypeCode(); @@ -72,7 +74,14 @@ final var record = (Type.Record) type; return DataType.StructType.from(record.getName() == null ? ProtoUtils.uniqueTypeName() : record.getName(), columns, record.isNullable()); case ARRAY: final var asArray = (Type.Array) type; - return DataType.ArrayType.from(toRelationalType(Assert.notNullUnchecked(asArray.getElementType())), asArray.isNullable()); + // Type.Array.getElementType() is @Nullable in fdb-record-layer-core (an untyped + // array literally has no element type), but Assert.notNullUnchecked enforces the + // non-null invariant expected here at runtime with a clear RelationalException; + // NullAway can't see that since Assert lives in the not-yet-migrated + // fdb-relational-api module. + @SuppressWarnings("NullAway") + final var elementType = Assert.notNullUnchecked(asArray.getElementType()); + return DataType.ArrayType.from(toRelationalType(elementType), asArray.isNullable()); case ENUM: final var asEnum = (Type.Enum) type; final var enumValues = asEnum.getEnumValues().stream().map(v -> DataType.EnumType.EnumValue.of(v.getName(), v.getNumber())).collect(Collectors.toList()); @@ -82,8 +91,7 @@ final var record = (Type.Record) type; // we do not have a representation of this type in the relational type system. return DataType.UnknownType.instance(); default: - Assert.failUnchecked(String.format(Locale.ROOT, "unexpected type %s", type)); - return null; // make compiler happy. + throw Assert.failUnchecked(String.format(Locale.ROOT, "unexpected type %s", type)); } } @@ -95,8 +103,6 @@ final var record = (Type.Record) type; * @param type The Relational data type. * @return The corresponding Record Layer type. */ - @SpotBugsSuppressWarnings(value = {"NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE"}, - justification = "should never happen, there is failUnchecked directly before that.") public static Type toRecordLayerType(final DataType type) { if (primitivesMap.containsKey(type)) { return primitivesMap.get(type); @@ -122,8 +128,7 @@ public static Type toRecordLayerType(final DataType type) { case UNKNOWN: return new Type.Any(); default: - Assert.failUnchecked(String.format(Locale.ROOT, "unexpected type %s", type)); - return null; // make compiler happy. + throw Assert.failUnchecked(String.format(Locale.ROOT, "unexpected type %s", type)); } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerColumn.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerColumn.java index 6b630cc7363..4eae575c823 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerColumn.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerColumn.java @@ -84,6 +84,9 @@ public static final class Builder { private int index; + // name and dataType are populated by the fluent setters below, so NullAway cannot see + // that they are always set before use in build(). + @SuppressWarnings("NullAway.Init") private Builder() { this.index = -1; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerIndex.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerIndex.java index 31e5471b5b2..6eb26fb654f 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerIndex.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerIndex.java @@ -119,7 +119,9 @@ public static RecordLayerIndex from(final String tableName, String tableStorageN .setTableName(tableName) .setTableStorageName(tableStorageName) .setKeyExpression(index.getRootExpression()) - .setPredicate(index.hasPredicate() ? index.getPredicate().toProto() : null) + // index.hasPredicate() guarantees getPredicate() is non-null; NullAway can't see + // that contract across the two separate method calls. + .setPredicate(index.hasPredicate() ? Objects.requireNonNull(index.getPredicate()).toProto() : null) .setOptions(index.getOptions()) .build(); } @@ -157,6 +159,13 @@ public static class Builder { @Nullable private Predicate predicate; + // tableName, tableStorageName, indexType, name, and keyExpression are populated by the + // fluent setters below and validated in build(), so NullAway cannot see that they are + // always set before use. + @SuppressWarnings("NullAway.Init") + private Builder() { + } + public Builder setTableName(String tableName) { this.tableName = tableName; return this; @@ -168,8 +177,10 @@ public Builder setTableStorageName(String tableStorageName) { } public Builder setTableType(Type.Record tableType) { - return setTableName(tableType.getName()) - .setTableStorageName(tableType.getStorageName()); + // tableType is always derived from a named table (never an anonymous nested record), + // so name and storageName are always present. + return setTableName(Objects.requireNonNull(tableType.getName(), "table type name is not set")) + .setTableStorageName(Objects.requireNonNull(tableType.getStorageName(), "table type storage name is not set")); } public Builder setIndexType(String indexType) { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java index fea9b1783b9..a1b578ab9a8 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java @@ -138,6 +138,10 @@ public static final class Builder { private UserDefinedFunction serializableFunction; private boolean isTemporary; + // Fields are populated via the fluent setters below and validated (non-null-checked) in + // build(), rather than through this constructor, so NullAway cannot see that they are + // always set before use; see the Assert.notNullUnchecked(...) calls in build(). + @SuppressWarnings("NullAway.Init") private Builder() { } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerSchemaTemplate.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerSchemaTemplate.java index bdc5a53f076..767f7c2022b 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerSchemaTemplate.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerSchemaTemplate.java @@ -50,6 +50,7 @@ import com.google.common.collect.Multimap; import com.google.protobuf.Descriptors; +import org.jspecify.annotations.Nullable; import java.util.ArrayList; import java.util.BitSet; import java.util.Collection; @@ -59,6 +60,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.TreeSet; @@ -392,9 +394,14 @@ public static final class Builder { private final Map storedQueries; - + // cachedMetadata is legitimately optional; it is only populated via setCachedMetadata() + // and build() branches on whether it was set. + @Nullable private RecordMetaData cachedMetadata; + // name is populated by the fluent setName() setter below and is required for build(); + // NullAway cannot see that it is always set before use. + @SuppressWarnings("NullAway.Init") private Builder() { tables = new LinkedHashMap<>(); auxiliaryTypes = new LinkedHashMap<>(); @@ -469,9 +476,12 @@ public Builder replaceInvokedRoutine(final RecordLayerInvokedRoutine invokedRout } public Builder removeInvokedRoutine(final String invokedRoutineName) { + // Bug fix: this branch is only reached when invokedRoutineName is NOT present, so + // invokedRoutines.get(invokedRoutineName) would always be null; the intent is simply + // to fail with a clear error rather than dereference a missing entry. if (!invokedRoutines.containsKey(invokedRoutineName)) { - Assert.thatUnchecked(invokedRoutines.get(invokedRoutineName).isTemporary(), ErrorCode.UNDEFINED_FUNCTION, - "attempt to non-existent temporary invoked routine!"); + Assert.failUnchecked(ErrorCode.UNDEFINED_FUNCTION, + "attempt to remove non-existent temporary invoked routine!"); } invokedRoutines.remove(invokedRoutineName); return this; @@ -549,7 +559,7 @@ public Builder setCachedMetadata(final RecordMetaData metadata) { } public RecordLayerTable findTableByStorageName(final String storageName) { - return tables.values().stream().filter(t -> t.getType().getStorageName().equals(storageName)) + return tables.values().stream().filter(t -> Objects.equals(t.getType().getStorageName(), storageName)) .findAny() .orElseThrow(() -> Assert.failUnchecked(ErrorCode.UNDEFINED_TABLE, "could not find '" + storageName + "'")); } @@ -668,7 +678,11 @@ private void resolveTypes() { for (final var auxiliaryType : auxiliaryTypes.entrySet()) { final var dataType = (DataType) auxiliaryType.getValue(); if (!dataType.isResolved()) { - resolvedAuxiliaryTypes.put(auxiliaryType.getKey(), (DataType.Named) ((DataType) resolvedTypes.get(auxiliaryType.getKey())).withNullable(dataType.isNullable())); + // Every auxiliary type key was included in namedTypes above and processed by + // the topological sort into resolvedTypes, so a lookup here always hits. + final var resolvedType = Objects.requireNonNull((DataType) resolvedTypes.get(auxiliaryType.getKey()), + "resolved type not found for '" + auxiliaryType.getKey() + "'"); + resolvedAuxiliaryTypes.put(auxiliaryType.getKey(), (DataType.Named) resolvedType.withNullable(dataType.isNullable())); } else { resolvedAuxiliaryTypes.put(auxiliaryType.getKey(), auxiliaryType.getValue()); } @@ -698,12 +712,15 @@ private static Set getDependencies(final DataType dataType, final Map< if (fieldType instanceof DataType.Named) { final var depName = ((DataType.Named) fieldType).getName(); Assert.thatUnchecked(types.containsKey(depName), ErrorCode.UNKNOWN_TYPE, "could not find type '%s'", depName); - mapBuilder.add(types.get(depName)); + // The Assert above guarantees the key is present; NullAway cannot see + // that a boolean assertion narrows a later, separate map lookup. + mapBuilder.add(Objects.requireNonNull(types.get(depName), "could not find type '" + depName + "'")); } else if (fieldType.getCode() == DataType.Code.ARRAY && ((DataType.ArrayType) fieldType).getElementType() instanceof DataType.Named) { final var asArray = (DataType.ArrayType) fieldType; final var depName = ((DataType.Named) asArray.getElementType()).getName(); Assert.thatUnchecked(types.containsKey(depName), ErrorCode.UNKNOWN_TYPE, "could not find type '%s'", depName); - mapBuilder.add(types.get(depName)); + // Same reasoning as above: the Assert just verified the key exists. + mapBuilder.add(Objects.requireNonNull(types.get(depName), "could not find type '" + depName + "'")); } } return mapBuilder.build(); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerTable.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerTable.java index 6db70121ae0..02c6320e96e 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerTable.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerTable.java @@ -205,6 +205,10 @@ public static final class Builder { private Record record; + // name, dataType, and record are populated by the fluent setters below (dataType/record + // are also lazily derived in build() if left unset) and validated in build(), so + // NullAway cannot see that they are always set before use. + @SuppressWarnings("NullAway.Init") private Builder() { this.indexes = new LinkedHashSet<>(); this.columns = ImmutableList.builder(); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerView.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerView.java index 7d48575d32e..325d1866cd8 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerView.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerView.java @@ -131,6 +131,10 @@ public static final class Builder { private boolean isTemporary; private Function compilableViewSupplier; + // description, name, and compilableViewSupplier are populated by the fluent setters + // below and validated in build(), so NullAway cannot see that they are always set before + // use. + @SuppressWarnings("NullAway.Init") private Builder() { } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/FileDescriptorSerializer.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/FileDescriptorSerializer.java index 2195d6df01e..420f4cb73f9 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/FileDescriptorSerializer.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/FileDescriptorSerializer.java @@ -33,9 +33,11 @@ import com.google.protobuf.DescriptorProtos; import com.google.protobuf.Descriptors; +import org.jspecify.annotations.Nullable; import java.util.LinkedHashSet; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; @@ -58,6 +60,8 @@ public class FileDescriptorSerializer extends SkeletonVisitor { // Dual-mode operation is temporary and should be removed once Relational has native support for some form of `ALTER` // commands that can `evolve` a table to new `generation`. In essence, we want generation assignment to happen at // a higher level, before the SchemaTemplate is made to serialize. + // Lazily determined from the first table's generations map (see checkTableGenerations); null until then. + @Nullable private Boolean assignGenerations; private int tableCounter; @@ -113,12 +117,14 @@ private String registerTypeDescriptors(final Type.Record type) { final var builder = TypeRepository.newBuilder(); type.defineProtoType(builder); final var typeDescriptors = builder.build(); - final var typeDescriptor = typeDescriptors.getMessageDescriptor(type).getName(); + // type was just defined into this same TypeRepository above, so the lookup always hits. + final var typeDescriptor = Objects.requireNonNull(typeDescriptors.getMessageDescriptor(type)).getName(); for (final var descriptorName : typeDescriptors.getMessageTypes()) { if (descriptorNames.contains(descriptorName)) { continue; } - final var descriptor = typeDescriptors.getMessageDescriptor(descriptorName); + // descriptorName was enumerated from this same typeDescriptors, so it always resolves. + final var descriptor = Objects.requireNonNull(typeDescriptors.getMessageDescriptor(descriptorName)); fileBuilder.addMessageType(descriptor.toProto()); descriptorNames.add(descriptorName); } @@ -126,7 +132,8 @@ private String registerTypeDescriptors(final Type.Record type) { if (enumNames.contains(enumName)) { continue; } - final var descriptor = typeDescriptors.getEnumDescriptor(enumName); + // enumName was enumerated from this same typeDescriptors, so it always resolves. + final var descriptor = Objects.requireNonNull(typeDescriptors.getEnumDescriptor(enumName)); fileBuilder.addEnumType(descriptor.toProto()); enumNames.add(enumName); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/RecordMetadataSerializer.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/RecordMetadataSerializer.java index da1689a2276..5cd552135d2 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/RecordMetadataSerializer.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/RecordMetadataSerializer.java @@ -42,6 +42,7 @@ import com.google.protobuf.Descriptors; +import java.util.Objects; @API(API.Status.EXPERIMENTAL) public class RecordMetadataSerializer extends SkeletonVisitor { @@ -64,7 +65,9 @@ public void visit(Table table) { Assert.thatUnchecked(table instanceof RecordLayerTable); final var recLayerTable = (RecordLayerTable) table; final KeyExpression keyExpression = recLayerTable.getPrimaryKey(); - final RecordTypeBuilder recordType = getBuilder().getRecordType(recLayerTable.getType().getStorageName()); + // A table's Record type is never anonymous, so storageName is always present. + final var storageName = Objects.requireNonNull(recLayerTable.getType().getStorageName()); + final RecordTypeBuilder recordType = getBuilder().getRecordType(storageName); recordType.setRecordTypeKey(recordTypeCounter++); recordType.setPrimaryKey(keyExpression); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metric/StoreTimerMetricCollector.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metric/StoreTimerMetricCollector.java index 00b8c1dc2b5..e543e2227df 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metric/StoreTimerMetricCollector.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metric/StoreTimerMetricCollector.java @@ -33,6 +33,7 @@ import com.codahale.metrics.MetricRegistry; import org.jspecify.annotations.Nullable; +import java.util.Objects; import java.util.concurrent.TimeUnit; import java.util.function.Function; @@ -59,9 +60,11 @@ @API(API.Status.EXPERIMENTAL) public final class StoreTimerMetricCollector implements MetricCollector { - private final Function timerLookup; + // The lookup's result is @Nullable: FDBRecordContext#getTimerForEvent(...) can return null when no timer + // is attached to the context (e.g. a transaction-bound database context) -- see fromFDBRecordContext(). + private final Function timerLookup; - private StoreTimerMetricCollector(final Function timerLookup) { + private StoreTimerMetricCollector(final Function timerLookup) { this.timerLookup = timerLookup; } @@ -95,7 +98,7 @@ public void increment(final RelationalMetric.RelationalCount count, final int va } @Override - public T clock(final RelationalMetric.RelationalEvent event, final Supplier supplier) throws RelationalException { + public T clock(final RelationalMetric.RelationalEvent event, final Supplier supplier) throws RelationalException { final long startNanos = System.nanoTime(); try { return supplier.get(); @@ -109,11 +112,16 @@ public T clock(final RelationalMetric.RelationalEvent event, final Supplier< @Override public double getAverageTimeMicrosForEvent(final RelationalMetric.RelationalEvent event) { - @Nullable final StoreTimer timer = timerLookup.apply(event); - Assert.notNullUnchecked(timer, ErrorCode.INTERNAL_ERROR, + final StoreTimer timerOrNull = timerLookup.apply(event); + // Reassign through notNullUnchecked (rather than discarding its result) so the non-null check + // actually narrows the value used below; Assert.notNullUnchecked can't narrow it on its own since + // Assert lives in the not-yet-migrated fdb-relational-api module. + @SuppressWarnings("NullAway") + final StoreTimer timer = Assert.notNullUnchecked(timerOrNull, ErrorCode.INTERNAL_ERROR, "Cannot read metrics: no backing store timer for event %s", event.title()); - final StoreTimer.Counter maybeCounter = timer.getCounter(event); - Assert.notNullUnchecked(maybeCounter, ErrorCode.INTERNAL_ERROR, + final StoreTimer.Counter maybeCounterOrNull = timer.getCounter(event); + @SuppressWarnings("NullAway") + final StoreTimer.Counter maybeCounter = Assert.notNullUnchecked(maybeCounterOrNull, ErrorCode.INTERNAL_ERROR, "Cannot find metrics associated for requested event: %s", event.title()); if (maybeCounter.getCount() == 0) { return 0.0; @@ -123,12 +131,17 @@ public double getAverageTimeMicrosForEvent(final RelationalMetric.RelationalEven @Override public long getCountsForCounter(final RelationalMetric.RelationalCount count) { - @Nullable final StoreTimer timer = timerLookup.apply(count); - Assert.notNullUnchecked(timer, ErrorCode.INTERNAL_ERROR, + final StoreTimer timerOrNull = timerLookup.apply(count); + @SuppressWarnings("NullAway") + final StoreTimer timer = Assert.notNullUnchecked(timerOrNull, ErrorCode.INTERNAL_ERROR, "Cannot read metrics: no backing store timer for count %s", count.title()); Assert.thatUnchecked(hasCounter(count), ErrorCode.INTERNAL_ERROR, "Cannot find metrics associated for requested event: %s", count.title()); - final StoreTimer.Counter counter = timer.getCounter(count); + // hasCounter(count) (just asserted true above) already established that timer.getCounter(count) != + // null; NullAway can't track that across the Assert.thatUnchecked call since Assert lives in the + // not-yet-migrated fdb-relational-api module. + @SuppressWarnings("NullAway") + final StoreTimer.Counter counter = Objects.requireNonNull(timer.getCounter(count)); Assert.thatUnchecked(counter.getTimeNanos() == 0, ErrorCode.INTERNAL_ERROR, "Event: %s records time and is probably a event timer", count.title()); return counter.getCount(); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizer.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizer.java index 2f7bcdce1fd..a38c4f14b6f 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizer.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizer.java @@ -195,13 +195,16 @@ public Void visitTerminal(TerminalNode node) { @Override public Object visitCreateTempFunction(final RelationalParser.CreateTempFunctionContext ctx) { - final var functionName = SemanticAnalyzer.normalizeString(ctx.tempSqlInvokedFunction().functionSpecification().schemaQualifiedRoutineName.getText(), caseSensitive); + // normalizeString() is @Nullable only when its input is null; schemaQualifiedRoutineName.getText() is + // never null for a parsed function name token, so the result here is never null either. + final var functionName = Objects.requireNonNull(SemanticAnalyzer.normalizeString( + ctx.tempSqlInvokedFunction().functionSpecification().schemaQualifiedRoutineName.getText(), caseSensitive)); queryHasherContextBuilder.getLiteralsBuilder().setScope(functionName); return visitChildren(ctx); } @Override - public Value visitUid(RelationalParser.UidContext ctx) { + public @Nullable Value visitUid(RelationalParser.UidContext ctx) { String uid = SemanticAnalyzer.normalizeString(ctx.getText(), caseSensitive); sqlCanonicalizer.append("\"").append(uid).append("\"").append(" "); return null; @@ -252,7 +255,7 @@ public Void visitLimitClauseAtom(RelationalParser.LimitClauseAtomContext ctx) { } @Override - public Object visitQuery(RelationalParser.QueryContext ctx) { + public @Nullable Object visitQuery(RelationalParser.QueryContext ctx) { if (queryCachingFlags.isEmpty()) { queryCachingFlags.add(NormalizationResult.QueryCachingFlags.IS_DQL_STATEMENT); } @@ -264,7 +267,7 @@ public Object visitQuery(RelationalParser.QueryContext ctx) { } @Override - public RelationalExpression visitStatementOptions(RelationalParser.StatementOptionsContext ctx) { + public @Nullable RelationalExpression visitStatementOptions(RelationalParser.StatementOptionsContext ctx) { for (final var opt : ctx.statementOption()) { visit(opt); } @@ -272,7 +275,7 @@ public RelationalExpression visitStatementOptions(RelationalParser.StatementOpti } @Override - public Object visitStatementOption(RelationalParser.StatementOptionContext ctx) { + public @Nullable Object visitStatementOption(RelationalParser.StatementOptionContext ctx) { try { if (ctx.NOCACHE() != null) { queryCachingFlags.add(NormalizationResult.QueryCachingFlags.WITH_NO_CACHE_OPTION); @@ -371,8 +374,9 @@ public Void visitScalarFunctionCall(RelationalParser.ScalarFunctionCallContext c } @Override - public Object visitPreparedStatementParameter(RelationalParser.PreparedStatementParameterContext ctx) { - Object param; + public @Nullable Object visitPreparedStatementParameter(RelationalParser.PreparedStatementParameterContext ctx) { + // A prepared parameter bound to SQL NULL is a legitimate value, hence @Nullable here. + @Nullable Object param; if (ctx.QUESTION() != null) { final int currentUnnamedParameterIndex = preparedStatementParameters.currentUnnamedParamIndex(); param = preparedStatementParameters.nextUnnamedParamValue(); @@ -424,7 +428,7 @@ public Object visitPreparedStatementParameter(RelationalParser.PreparedStatement } @Override - public Object visitInPredicate(RelationalParser.InPredicateContext ctx) { + public @Nullable Object visitInPredicate(RelationalParser.InPredicateContext ctx) { if (ctx.NOT() != null) { ctx.NOT().accept(this); } @@ -574,17 +578,17 @@ private void processScalarLiteral(final Object literal, final int tokenIndex) { processLiteral(literal, tokenIndex, null, null); } - private void processUnnamedParameter(final Object literal, final int unnamedParameterIndex, + private void processUnnamedParameter(@Nullable final Object literal, final int unnamedParameterIndex, final int tokenIndex) { processLiteral(literal, tokenIndex, unnamedParameterIndex, null); } - private void processNamedParameter(final Object literal, final String parameterName, + private void processNamedParameter(@Nullable final Object literal, final String parameterName, final int tokenIndex) { processLiteral(literal, tokenIndex, null, parameterName); } - private void processLiteral(final Object literal, final int tokenIndex, + private void processLiteral(@Nullable final Object literal, final int tokenIndex, @Nullable final Integer unnamedParameterIndex, @Nullable final String parameterName) { if (allowLiteralAddition) { queryHasherContextBuilder.getLiteralsBuilder() diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/FieldValueTrieNode.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/FieldValueTrieNode.java index 88fbc3d6125..0871ea0756c 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/FieldValueTrieNode.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/FieldValueTrieNode.java @@ -82,7 +82,7 @@ public boolean equals(final Object o) { } @SuppressWarnings("PMD.CompareObjectsWithEquals") - public boolean semanticEquals(final Object other, final AliasMap equivalencesMap) { + public boolean semanticEquals(@Nullable final Object other, final AliasMap equivalencesMap) { if (this == other) { return true; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Literals.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Literals.java index 5eb664a25df..2a823fea322 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Literals.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Literals.java @@ -187,7 +187,8 @@ public Optional getFirstValueDuplicateMaybe(@Nullable Object val if (current.size() > 1) { return Optional.empty(); } - return Optional.of(literalReverseLookup.get(value)); + // Note: this must be ofNullable, not of() -- a missing key legitimately means "no duplicate found". + return Optional.ofNullable(literalReverseLookup.get(value)); } public Optional getFirstDuplicateOfConstantIdMaybe(String constantId) { @@ -196,7 +197,8 @@ public Optional getFirstDuplicateOfConstantIdMaybe(String consta if (current.size() > 1) { return Optional.empty(); } - return Optional.of(literalReverseLookup.get(literals.stream().filter(l -> + // Note: this must be ofNullable, not of() -- a missing key legitimately means "no duplicate found". + return Optional.ofNullable(literalReverseLookup.get(literals.stream().filter(l -> l.getConstantId().equals(constantId)).findFirst().orElseThrow().getLiteralObject())); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperator.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperator.java index 8cb08a2479f..a74204ee100 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperator.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperator.java @@ -258,8 +258,7 @@ public static LogicalOperator generateTableAccess(Identifier tableId, // if we fully supported invisible columns (see: https://github.com/FoundationDB/fdb-record-layer/pull/3787) type = type.addPseudoFields(); } - final String storageName = type.getStorageName(); - Assert.thatUnchecked(storageName != null, "storage name for table access must not be null"); + final String storageName = Objects.requireNonNull(type.getStorageName(), "storage name for table access must not be null"); final var typeFilterExpression = LogicalTypeFilterExpression.of(ImmutableSet.of(storageName), scanExpression, type); final var resultingQuantifier = Quantifier.forEach(Reference.initialOf(typeFilterExpression)); final ImmutableList.Builder attributesBuilder = ImmutableList.builder(); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/NormalizedQueryExecutionContext.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/NormalizedQueryExecutionContext.java index c6135d23994..bae90bd03b2 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/NormalizedQueryExecutionContext.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/NormalizedQueryExecutionContext.java @@ -107,6 +107,10 @@ public static final class Builder { @Nullable private PlanHashMode planHashMode; + // continuation is byte[], and NullAway does not reliably respect @Nullable annotations on array-typed + // fields (a known limitation, also worked around in fdb-relational-grpc); it misreports this @Nullable + // field as @NonNull below. + @SuppressWarnings("NullAway") private Builder() { this.literalsBuilder = Literals.newBuilder(); this.isForExplain = false; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/OrderByExpression.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/OrderByExpression.java index 01133171fc8..1ba7555ac73 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/OrderByExpression.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/OrderByExpression.java @@ -83,13 +83,20 @@ public static Stream pullUp(final Stream o // the structural matching inside `pullUp()`. final var underlying = orderByExpression.getUnderlying() .simplify(EvaluationContext.empty(), aliasMap, constantAliases); + // replace() is declared @Nullable in general (it returns null if the replacement operator + // returns null for any node), but our operator below never returns null; Assert.notNullUnchecked + // enforces that at runtime with a clear RelationalException, but NullAway can't see that since + // Assert lives in the not-yet-migrated fdb-relational-api module. + @SuppressWarnings("NullAway") final var pulledUpUnderlying = Assert.notNullUnchecked(underlying.replace( subExpression -> { final var pulledUpExpressionMap = simplifiedValue.pullUp(List.of(subExpression), EvaluationContext.empty(), aliasMap, constantAliases, correlationIdentifier); if (pulledUpExpressionMap.containsKey(subExpression) && !pulledUpExpressionMap.get(subExpression).isEmpty()) { - return Iterables.getFirst(pulledUpExpressionMap.get(subExpression), null); + // the emptiness check above guarantees this always returns an actual element, so + // subExpression (rather than null) is passed as the unused fallback default. + return Iterables.getFirst(pulledUpExpressionMap.get(subExpression), subExpression); } return subExpression; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanContext.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanContext.java index 734d8be0aaa..094ffbbe875 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanContext.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanContext.java @@ -152,6 +152,10 @@ public static final class Builder { private boolean isCaseSensitive; + // Fields are populated via the fluent with*()/from*() methods below and validated + // (non-null-checked) in verify(), rather than through this constructor, so NullAway cannot + // see that they are always set before use; see the Assert.notNull(...) calls in verify(). + @SuppressWarnings("NullAway.Init") private Builder() { } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java index 508b9d28586..103b30ef57e 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java @@ -86,6 +86,7 @@ import java.util.function.BiFunction; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; +import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.StreamSupport; @@ -279,7 +280,14 @@ public Set getAllTableStorageNames() { try { return metadataCatalog.getTables().stream() .map(table -> Assert.castUnchecked(table, RecordLayerTable.class)) - .map(table -> Assert.notNullUnchecked(table.getType().getStorageName())) + // A table's DataType always has a storage name; DataType.getStorageName() is @Nullable + // only because it's shared with non-table types, but Assert.notNullUnchecked can't + // narrow that here since Assert lives in the not-yet-migrated fdb-relational-api module. + .map(table -> { + @SuppressWarnings("NullAway") + final String storageName = Assert.notNullUnchecked(table.getType().getStorageName()); + return storageName; + }) .collect(ImmutableSet.toImmutableSet()); } catch (RelationalException e) { throw e.toUncheckedWrappedException(); @@ -637,8 +645,14 @@ public static ParsedTypeInfo ofCustomType(final Identifier customType, } public DataType lookupBuiltInType(final ParsedTypeInfo parsedTypeInfo) { - Assert.thatUnchecked(!parsedTypeInfo.hasCustomType(), ErrorCode.INTERNAL_ERROR, () -> "unexpected custom type " + - Assert.notNullUnchecked(parsedTypeInfo.getCustomType()).getName()); + // The message supplier below is only invoked when the assertion is false, i.e. when + // hasCustomType() is true, i.e. when getCustomType() (== "customType != null", see ParsedTypeInfo + // above) is guaranteed non-null; NullAway can't see that invariant, and Assert.notNullUnchecked + // can't narrow it either since Assert lives in the not-yet-migrated fdb-relational-api module. + @SuppressWarnings("NullAway") + final Supplier unexpectedCustomTypeMessage = () -> "unexpected custom type " + + Assert.notNullUnchecked(parsedTypeInfo.getCustomType()).getName(); + Assert.thatUnchecked(!parsedTypeInfo.hasCustomType(), ErrorCode.INTERNAL_ERROR, unexpectedCustomTypeMessage); return lookupType(parsedTypeInfo, typeToLookUp -> { Assert.failUnchecked("unexpected custom type " + typeToLookUp); return Optional.empty(); @@ -649,12 +663,18 @@ public DataType lookupType(final ParsedTypeInfo parsedTypeInfo, final Function> dataTypeProvider) { DataType type; final var isNullable = parsedTypeInfo.isNullable(); + // hasCustomType()/hasPrimitiveType() are exactly "customType/primitiveTypeContext != null" (see + // ParsedTypeInfo above), so the notNullUnchecked calls below are safe given these guards; NullAway + // can't see that invariant, and Assert.notNullUnchecked can't narrow it either since Assert lives + // in the not-yet-migrated fdb-relational-api module. if (parsedTypeInfo.hasCustomType()) { + @SuppressWarnings("NullAway") final var typeName = Assert.notNullUnchecked(parsedTypeInfo.getCustomType()).getName(); final var maybeFound = dataTypeProvider.apply(typeName); // if we cannot find the type now, mark it, we will try to resolve it later on via a second pass. type = maybeFound.map(dataType -> dataType.withNullable(isNullable)).orElseGet(() -> DataType.UnresolvedType.of(typeName, isNullable)); } else { + @SuppressWarnings("NullAway") final var primitiveType = Assert.notNullUnchecked(parsedTypeInfo.getPrimitiveTypeContext()); if (primitiveType.vectorType() != null) { final var vectorTypeCtx = primitiveType.vectorType(); @@ -671,7 +691,9 @@ public DataType lookupType(final ParsedTypeInfo parsedTypeInfo, Assert.thatUnchecked(length > 0, ErrorCode.SYNTAX_ERROR, "vector dimension must be positive"); type = DataType.VectorType.of(precision, length, isNullable); } else { - final var primitiveTypeName = parsedTypeInfo.getPrimitiveTypeContext().getText(); + // Reuse the already-validated primitiveType (from just above) instead of re-fetching it via + // the @Nullable getter. + final var primitiveTypeName = primitiveType.getText(); switch (primitiveTypeName.toUpperCase(Locale.ROOT)) { case "STRING": @@ -783,18 +805,31 @@ public static Optional validateUnionTypes(LogicalOperators unionLeg continue; } if (requiresPromotion) { - result = Assert.castUnchecked(Type.maximumType(result, unionLegType), Type.Record.class); + result = maximumRecordTypeOrFail(result, unionLegType); continue; } final var oldType = result; - result = Assert.castUnchecked(Assert.notNullUnchecked(Type.maximumType(result, unionLegType), ErrorCode.UNION_INCOMPATIBLE_COLUMNS, - "Incompatible column types in UNION legs"), - Type.Record.class); + result = maximumRecordTypeOrFail(result, unionLegType); if (!oldType.equals(result)) { requiresPromotion = true; } } - return requiresPromotion ? Optional.of(Assert.notNullUnchecked(result)) : Optional.empty(); + // requiresPromotion is only set to true after a successful, non-null assignment to result above, so + // this is never actually null; NullAway can't see that invariant, and Assert.notNullUnchecked can't + // narrow it either since Assert lives in the not-yet-migrated fdb-relational-api module. + @SuppressWarnings("NullAway") + final Type.Record nonNullResult = Assert.notNullUnchecked(result); + return requiresPromotion ? Optional.of(nonNullResult) : Optional.empty(); + } + + // Type.maximumType() can legitimately return null for incompatible types; Assert.notNullUnchecked + // enforces that with a clear RelationalException, but NullAway can't see through it since Assert lives + // in the not-yet-migrated fdb-relational-api module. + @SuppressWarnings("NullAway") + private static Type.Record maximumRecordTypeOrFail(final Type.Record left, final Type.Record right) { + return Assert.castUnchecked(Assert.notNullUnchecked(Type.maximumType(left, right), ErrorCode.UNION_INCOMPATIBLE_COLUMNS, + "Incompatible column types in UNION legs"), + Type.Record.class); } public Type.Array resolveArrayTypeFromValues(Expressions arrayItems) { @@ -869,8 +904,12 @@ public static void validateLimit(Expression expression) { final long maxInclusive = Integer.MAX_VALUE; final var underlying = expression.getUnderlying(); Assert.thatUnchecked(underlying instanceof LiteralValue); - final var value = ((LiteralValue) underlying).getLiteralValue(); - Assert.notNullUnchecked(value, ErrorCode.INVALID_ROW_COUNT_IN_LIMIT_CLAUSE, + final var underlyingValue = ((LiteralValue) underlying).getLiteralValue(); + // Reassign through notNullUnchecked (rather than discarding its result) so the non-null check + // actually narrows the value used below; Assert.notNullUnchecked can't narrow it on its own since + // Assert lives in the not-yet-migrated fdb-relational-api module. + @SuppressWarnings("NullAway") + final Object value = Assert.notNullUnchecked(underlyingValue, ErrorCode.INVALID_ROW_COUNT_IN_LIMIT_CLAUSE, () -> String.format(Locale.ROOT, "limit value out of range [1, %d]", Integer.MAX_VALUE)); if (value.getClass() == Integer.class) { Assert.thatUnchecked(minInclusive <= ((Integer) value) && ((Integer) value) <= maxInclusive, @@ -927,8 +966,12 @@ public static void validateContinuation(final Expression continuation) { final var underlying = continuation.getUnderlying(); Assert.thatUnchecked(underlying instanceof LiteralValue, ErrorCode.INVALID_CONTINUATION, "Unexpected continuation parameter of type %s", underlying.getClass().getSimpleName()); - final var continuationBytes = Assert.castUnchecked(underlying, LiteralValue.class).getLiteralValue(); - Assert.notNullUnchecked(continuationBytes); + final var underlyingBytes = Assert.castUnchecked(underlying, LiteralValue.class).getLiteralValue(); + // Reassign through notNullUnchecked (rather than discarding its result) so the non-null check + // actually narrows the value used below; Assert.notNullUnchecked can't narrow it on its own since + // Assert lives in the not-yet-migrated fdb-relational-api module. + @SuppressWarnings("NullAway") + final Object continuationBytes = Assert.notNullUnchecked(underlyingBytes); Assert.thatUnchecked(continuationBytes instanceof ByteString, ErrorCode.INVALID_CONTINUATION, "Unexpected continuation parameter of type %s", continuationBytes.getClass().getSimpleName()); } @@ -1110,14 +1153,17 @@ public Optional getRecursiveCteType(final RelationalParser.QueryContext na final AtomicReference> result = new AtomicReference<>(Optional.empty()); recursiveQueryTraversal(namedQueryBody, queryName, idParser, nonRecursiveBranch -> { - if (result.get().isEmpty()) { + // result is always set to a non-null Optional (initially Optional.empty(), later + // Optional.of(...) below); AtomicReference#get() is only @Nullable in general because + // the JDK API permits storing null, which this usage never does. + if (Objects.requireNonNull(result.get()).isEmpty()) { final var logicalOperator = handleQueryFragment(nonRecursiveBranch, namedQueryBody, memoizer, queryVisitor); result.set(Optional.of(logicalOperator.getQuantifier().getFlowedObjectType())); } }, ignored -> { }); - return result.get(); + return Objects.requireNonNull(result.get()); } /** diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Star.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Star.java index 4aa24383d37..2b19071c049 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Star.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Star.java @@ -82,14 +82,12 @@ public Expression withQualifier(Collection qualifier) { @Override public Expression withName(Identifier name) { - Assert.failUnchecked("attempt to name a star expression"); - return null; + throw Assert.failUnchecked("attempt to name a star expression"); } @Override public Expression withUnderlying(Value underlying) { - Assert.failUnchecked("attempt to replace underlying value of a star expression"); - return null; + throw Assert.failUnchecked("attempt to replace underlying value of a star expression"); } /** diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/MultiStageCache.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/MultiStageCache.java index 21ed72e4966..e0d791b2cda 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/MultiStageCache.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/MultiStageCache.java @@ -110,6 +110,7 @@ public class MultiStageCache extends AbstractCache { @Nullable private final Executor secondaryExecutor; + @Nullable private final Executor tertiaryExecutor; @Nullable diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/RelationalPlanCache.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/RelationalPlanCache.java index a2ba7623cae..fe720707089 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/RelationalPlanCache.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/cache/RelationalPlanCache.java @@ -25,6 +25,7 @@ import com.apple.foundationdb.relational.recordlayer.query.Plan; import com.google.common.base.Ticker; import org.jspecify.annotations.Nullable; +import java.util.Objects; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; @@ -59,14 +60,17 @@ private RelationalPlanCache(int size, public static final class RelationalCacheBuilder extends MultiStageCache.Builder, RelationalCacheBuilder> { public RelationalCacheBuilder() { - size = (Integer) (Options.defaultOptions().get(Options.Name.PLAN_CACHE_PRIMARY_MAX_ENTRIES)); - secondarySize = (Integer) (Options.defaultOptions().get(Options.Name.PLAN_CACHE_SECONDARY_MAX_ENTRIES)); - tertiarySize = (Integer) (Options.defaultOptions().get(Options.Name.PLAN_CACHE_TERTIARY_MAX_ENTRIES)); - ttl = (Long) (Options.defaultOptions().get(Options.Name.PLAN_CACHE_PRIMARY_TIME_TO_LIVE_MILLIS)); + // Options.defaultOptions() is a fixed map that is always populated with an entry for every + // Options.Name (including the PLAN_CACHE_* names below), so these lookups never actually + // return null; Objects.requireNonNull documents that invariant for NullAway. + size = (Integer) Objects.requireNonNull(Options.defaultOptions().get(Options.Name.PLAN_CACHE_PRIMARY_MAX_ENTRIES), "no default registered for PLAN_CACHE_PRIMARY_MAX_ENTRIES"); + secondarySize = (Integer) Objects.requireNonNull(Options.defaultOptions().get(Options.Name.PLAN_CACHE_SECONDARY_MAX_ENTRIES), "no default registered for PLAN_CACHE_SECONDARY_MAX_ENTRIES"); + tertiarySize = (Integer) Objects.requireNonNull(Options.defaultOptions().get(Options.Name.PLAN_CACHE_TERTIARY_MAX_ENTRIES), "no default registered for PLAN_CACHE_TERTIARY_MAX_ENTRIES"); + ttl = (Long) Objects.requireNonNull(Options.defaultOptions().get(Options.Name.PLAN_CACHE_PRIMARY_TIME_TO_LIVE_MILLIS), "no default registered for PLAN_CACHE_PRIMARY_TIME_TO_LIVE_MILLIS"); ttlTimeUnit = DEFAULT_TTL_TIME_UNIT; - secondaryTtl = (Long) (Options.defaultOptions().get(Options.Name.PLAN_CACHE_SECONDARY_TIME_TO_LIVE_MILLIS)); + secondaryTtl = (Long) Objects.requireNonNull(Options.defaultOptions().get(Options.Name.PLAN_CACHE_SECONDARY_TIME_TO_LIVE_MILLIS), "no default registered for PLAN_CACHE_SECONDARY_TIME_TO_LIVE_MILLIS"); secondaryTtlTimeUnit = DEFAULT_SECONDARY_TTL_TIME_UNIT; - tertiaryTtl = (Long) (Options.defaultOptions().get(Options.Name.PLAN_CACHE_TERTIARY_TIME_TO_LIVE_MILLIS)); + tertiaryTtl = (Long) Objects.requireNonNull(Options.defaultOptions().get(Options.Name.PLAN_CACHE_TERTIARY_TIME_TO_LIVE_MILLIS), "no default registered for PLAN_CACHE_TERTIARY_TIME_TO_LIVE_MILLIS"); tertiaryTtlTimeUnit = DEFAULT_TERTIARY_TTL_TIME_UNIT; executor = null; secondaryExecutor = null; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/MaterializedViewIndexGenerator.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/MaterializedViewIndexGenerator.java index 3a4a2a09283..bcc76fde80b 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/MaterializedViewIndexGenerator.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/MaterializedViewIndexGenerator.java @@ -262,7 +262,7 @@ private List collectResultValues(Value value) { // Make sure the grouping values and the result values are consistent if (groupingValues == null) { // This shouldn't happen unless there's more than one indexable aggregate value - Assert.failUnchecked(ErrorCode.UNSUPPORTED_OPERATION, "Grouping values absent from aggregate result value"); + throw Assert.failUnchecked(ErrorCode.UNSUPPORTED_OPERATION, "Grouping values absent from aggregate result value"); } final var simplifiedGroupingValues = Values.deconstructRecord(groupingValues).stream() @@ -561,17 +561,20 @@ private KeyExpression toKeyExpression(Value value) { } else if (value instanceof LiteralValue) { return Key.Expressions.value(((LiteralValue) value).getLiteralValue()); } else { - Assert.failUnchecked(ErrorCode.UNSUPPORTED_OPERATION, "unable to construct expression"); - return null; + throw Assert.failUnchecked(ErrorCode.UNSUPPORTED_OPERATION, "unable to construct expression"); } } private static KeyExpression toKeyExpression(FieldValueTrieNode trieNode, Map orderingFunctions) { - Assert.notNullUnchecked(trieNode.getChildrenMap()); - Assert.thatUnchecked(!trieNode.getChildrenMap().isEmpty()); + // FieldValueTrieNode.getChildrenMap() (fdb-record-layer-core) is @Nullable for leaf + // nodes; Assert.notNullUnchecked enforces the non-leaf invariant expected here at + // runtime with a clear RelationalException, but NullAway can't see that since Assert + // lives in the not-yet-migrated fdb-relational-api module. + @SuppressWarnings("NullAway") + final var childrenMap = Assert.notNullUnchecked(trieNode.getChildrenMap()); + Assert.thatUnchecked(!childrenMap.isEmpty()); - final var childrenMap = trieNode.getChildrenMap(); final var exprConstituents = childrenMap.entrySet().stream().map(nodeEntry -> { final FieldValue.ResolvedAccessor accessor = nodeEntry.getKey(); final FieldValueTrieNode node = nodeEntry.getValue(); @@ -744,7 +747,12 @@ private Value dereference(Value value) { final var valueWithChild = (ValueWithChild) value; return valueWithChild.withNewChild(dereference(valueWithChild.getChild())); } else if (value instanceof QuantifiedObjectValue) { - return dereference(correlatedKeyExpressions.get(value.getCorrelatedTo().stream().findFirst().orElseThrow())); + final var alias = value.getCorrelatedTo().stream().findFirst().orElseThrow(); + // Every quantifier is registered into correlatedKeyExpressions by + // collectQuantifiers/collectQuantifiersInternal before any value referencing it is + // dereferenced, so the lookup here always hits. + return dereference(Objects.requireNonNull(correlatedKeyExpressions.get(alias), + () -> "no correlated value found for alias " + alias)); } else if (value instanceof ArithmeticValue) { final List newChildren = new ArrayList<>(); for (Value v:value.getChildren()) { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/OnSourceIndexGenerator.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/OnSourceIndexGenerator.java index 1543a0cd4ae..38c48d5568c 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/OnSourceIndexGenerator.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/OnSourceIndexGenerator.java @@ -188,14 +188,21 @@ public RecordLayerIndex.Builder generate() { .addAll(keyIdentifiers) .addAll(valueIdentifiers) .build().stream().map(identifier -> { - final var column = originalOutputMap.get(identifier); - Assert.notNullUnchecked(column, ErrorCode.UNDEFINED_COLUMN, () -> "could not find " + identifier); + // originalOutputMap.get(identifier) is @Nullable only because Map.get() is + // generically nullable; Assert.notNullUnchecked enforces that every + // projected identifier is actually present with a clear RelationalException, + // but NullAway can't see that since Assert lives in the not-yet-migrated + // fdb-relational-api module. + @SuppressWarnings("NullAway") + final var column = Assert.notNullUnchecked(originalOutputMap.get(identifier), ErrorCode.UNDEFINED_COLUMN, () -> "could not find " + identifier); return column; }).collect(ImmutableList.toImmutableList()); final List orderByExpressions = keyColumns.stream().map(keyColumn -> { - final var column = originalOutputMap.get(keyColumn.getIdentifier()); - Assert.notNullUnchecked(column, ErrorCode.UNDEFINED_COLUMN, () -> "could not find " + keyColumn.getIdentifier()); + // Same reasoning as above: Assert.notNullUnchecked enforces the real invariant at + // runtime; NullAway can't see through the not-yet-migrated Assert utility. + @SuppressWarnings("NullAway") + final var column = Assert.notNullUnchecked(originalOutputMap.get(keyColumn.getIdentifier()), ErrorCode.UNDEFINED_COLUMN, () -> "could not find " + keyColumn.getIdentifier()); return OrderByExpression.of(Expression.fromColumn(column), keyColumn.isDescending(), keyColumn.isNullsLast()); }).collect(ImmutableList.toImmutableList()); @@ -321,6 +328,10 @@ public static final class Builder { private RecordLayerSchemaTemplate.Builder metadataBuilder; + // indexName, indexSource, semanticAnalyzer, and metadataBuilder are populated by the + // fluent setters below and validated before use in build(), so NullAway cannot see that + // they are always set before use. + @SuppressWarnings("NullAway.Init") private Builder() { this.keyColumns = new ArrayList<>(); this.valueColumns = new ArrayList<>(); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/CompiledSqlFunction.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/CompiledSqlFunction.java index 4aae245b6e8..12cb815e8c0 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/CompiledSqlFunction.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/CompiledSqlFunction.java @@ -159,9 +159,13 @@ static final class CompiledSQLFunctionStepBuilder implements UserDefinedFunction private final RelationalExpression body; private final Expressions parameters; private final List> parameterDefaults; + @Nullable private final ForEach parametersQuantifier; private Literals literals; + // Assert.isNullUnchecked's own parameter isn't @Nullable (Assert lives in the not-yet-migrated + // fdb-relational-api module), even though its entire purpose is to check a value that may be null. + @SuppressWarnings("NullAway") CompiledSQLFunctionStepBuilder(final String name, final RelationalExpression body, final Expressions parameters, diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedFunctionBuilder.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedFunctionBuilder.java index 86aeff1b18b..bd018dc8f1b 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedFunctionBuilder.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedFunctionBuilder.java @@ -187,6 +187,9 @@ public static final class UserDefinedFunctionSignatureStepBuilder implements Sig private Quantifier.ForEach parametersQuantifier; private Type returnType; + // name, parameters, parametersQuantifier and returnType are populated by the fluent setters below, + // so NullAway cannot see that they are always set before use (enforced by this builder's callers). + @SuppressWarnings("NullAway.Init") private UserDefinedFunctionSignatureStepBuilder() { this.parametersBuilder = ImmutableList.builder(); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedMacroFunctionBuilder.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedMacroFunctionBuilder.java index 83f56cbde46..ee96b0f8289 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedMacroFunctionBuilder.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/UserDefinedMacroFunctionBuilder.java @@ -155,8 +155,14 @@ private Value translateBodyValueParametersCorrelations(final List RecordConstructorValue.ofColumns(columnBuilder.build())) .build(); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/BaseVisitor.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/BaseVisitor.java index 3e80e83d5cb..afb6170ab37 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/BaseVisitor.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/BaseVisitor.java @@ -218,6 +218,11 @@ boolean isForDdl() { return getPlanGenerationContext().isForDdl(); } + // SemanticAnalyzer.normalizeString() is @Nullable only when its input is null; value here is @NonNull, so the + // result is never null. Assert.notNullUnchecked enforces that invariant at runtime with a clear + // RelationalException, but NullAway can't see that since Assert lives in the not-yet-migrated + // fdb-relational-api module. + @SuppressWarnings("NullAway") protected String normalizeString(final String value) { return Assert.notNullUnchecked(SemanticAnalyzer.normalizeString(value, caseSensitive)); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/ExpressionVisitor.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/ExpressionVisitor.java index 1f874dc2c17..fa66d32ce9f 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/ExpressionVisitor.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/ExpressionVisitor.java @@ -234,7 +234,9 @@ public NonnullPair } private static RecordLayerColumn toColumn(FieldValue.ResolvedAccessor field, CompatibleTypeEvolutionPredicate.FieldAccessTrieNode columnIdTrie) { - final var columnName = field.getName(); + // field is always constructed from an Identifier's name (see visitUidListWithNestings), which is never + // null, even though ResolvedAccessor.getName() is declared @Nullable in general. + final var columnName = Objects.requireNonNull(field.getName(), "inline table column must have a name"); final var builder = RecordLayerColumn.newBuilder().setName(columnName).setIndex(field.getOrdinal()); if (columnIdTrie.getChildrenMap() == null) { return builder.setDataType(DataTypeUtils.toRelationalType(field.getType())).build(); @@ -484,8 +486,7 @@ public Expression visitDataTypeFunctionCall(RelationalParser.DataTypeFunctionCal return Expression.ofUnnamed(targetDataType, value); } - Assert.failUnchecked(ErrorCode.UNSUPPORTED_OPERATION, "CONVERT function is not yet supported"); - return null; + throw Assert.failUnchecked(ErrorCode.UNSUPPORTED_OPERATION, "CONVERT function is not yet supported"); } @Override @@ -563,8 +564,7 @@ public Expression visitPredicatedExpression(final RelationalParser.PredicatedExp if (predicate instanceof RelationalParser.IsExpressionContext) { return visitIsExpression(operand, (RelationalParser.IsExpressionContext)predicate); } - Assert.failUnchecked(ErrorCode.UNSUPPORTED_QUERY, "unsupported predicate " + ctx.predicate().getText()); - return null; + throw Assert.failUnchecked(ErrorCode.UNSUPPORTED_QUERY, "unsupported predicate " + ctx.predicate().getText()); } @Override @@ -838,8 +838,7 @@ public Expression visitBooleanConstant(RelationalParser.BooleanConstantContext c @Override public Expression visitBitStringConstant(RelationalParser.BitStringConstantContext ctx) { - Assert.failUnchecked(ErrorCode.UNSUPPORTED_QUERY, "bit strings not supported"); - return null; + throw Assert.failUnchecked(ErrorCode.UNSUPPORTED_QUERY, "bit strings not supported"); } @Override @@ -942,6 +941,11 @@ public Expression visitArrayConstructor(RelationalParser.ArrayConstructorContext } final var arrayTargetType = Assert.castUnchecked(targetTypeMaybe.get(), Type.Array.class); + // arrayTargetType.getElementType() is @Nullable only for an erased array type, which cannot occur here since + // the target type was propagated down from a resolved schema/expression type; Assert.notNullUnchecked + // enforces that invariant at runtime with a clear RelationalException, but NullAway can't see that since + // Assert lives in the not-yet-migrated fdb-relational-api module. + @SuppressWarnings("NullAway") final var newStateBuilder = LogicalPlanFragment.State.newBuilder().withTargetType(Assert.notNullUnchecked(arrayTargetType.getElementType())); try { getDelegate().getCurrentPlanFragment().setState(newStateBuilder.build()); @@ -971,7 +975,9 @@ private Expression parseRecordField(ParserRuleContext parserRuleContext, if (targetField != null && maybeState.isPresent() && maybeState.get().getTargetTypeReorderings().isPresent()) { reorderings = maybeState.get().getTargetTypeReorderings().get(); } - final var targetFieldReorderings = (reorderings == null || reorderings.getChildrenMap() == null) ? + // reorderings is only ever assigned (above) when targetField is non-null, so the extra targetField == null + // check below is redundant at runtime but lets NullAway see that targetField.getFieldName() is safe. + final var targetFieldReorderings = (targetField == null || reorderings == null || reorderings.getChildrenMap() == null) ? null : reorderings.getChildrenMap().get(targetField.getFieldName()); final var newStateBuilder = LogicalPlanFragment.State.newBuilder(); @@ -992,6 +998,9 @@ private Expression parseRecordField(ParserRuleContext parserRuleContext, if (fieldType == null) { return expression; } + // fieldType is derived from targetField.getFieldType() above, so fieldType being non-null implies + // targetField is also non-null; reassign so NullAway can see that for the rest of this method. + targetField = Objects.requireNonNull(targetField); var coercedExpression = coerceIfNecessary(expression, fieldType); if (targetField.getFieldIndexOptional().isPresent()) { coercedExpression = coercedExpression.withUnderlying(new ColumnarValue(coercedExpression.getUnderlying(), @@ -1026,7 +1035,12 @@ private static Value coerceValueIfNecessary(Value value, Type targetType) { } if (resultType.isArray() && PromoteValue.isPromotionNeeded(resultType, targetType) && value instanceof AbstractArrayConstructorValue) { Assert.thatUnchecked(targetType.isArray(), "Cannot convert array type to non-array type"); - final var targetElementType = ((Type.Array) targetType).getElementType(); + // getElementType() is @Nullable only for an erased array type; targetType here always originates from a + // resolved schema/expression type, so it is never erased. Assert.notNullUnchecked enforces that + // invariant at runtime with a clear RelationalException, but NullAway can't see that since Assert lives + // in the not-yet-migrated fdb-relational-api module. + @SuppressWarnings("NullAway") + final Type targetElementType = Assert.notNullUnchecked(((Type.Array) targetType).getElementType()); return AbstractArrayConstructorValue.LightArrayConstructorValue.of(Streams.stream(value.getChildren()).map(c -> coerceValueIfNecessary(c, targetElementType)).collect(Collectors.toList())); } return value; @@ -1043,6 +1057,11 @@ private Expressions parseRecordFieldsUnderReorderings(final Listbuilder(); @@ -1055,7 +1074,7 @@ private Expressions parseRecordFieldsUnderReorderings(final List= providedColumnContexts.size()) { // column is declared but the value is not provided - Assert.failUnchecked(ErrorCode.SYNTAX_ERROR, "Value of column \"" + elementField.getFieldName() + "\" is not provided"); + throw Assert.failUnchecked(ErrorCode.SYNTAX_ERROR, "Value of column \"" + elementField.getFieldName() + "\" is not provided"); } else { // We do not yet support default values for any types, hence it makes sense to simply fail if the field type // expects non-null but no value is provided. diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/IdentifierVisitor.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/IdentifierVisitor.java index 14b7d88afb8..1ae3cd09546 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/IdentifierVisitor.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/IdentifierVisitor.java @@ -88,22 +88,19 @@ public Identifier visitSimpleId(RelationalParser.SimpleIdContext simpleIdContext @Override // not supported yet @ExcludeFromJacocoGeneratedReport public Identifier visitIndexColumnName(RelationalParser.IndexColumnNameContext ctx) { - Assert.failUnchecked(ErrorCode.UNSUPPORTED_QUERY, "setting index column is not supported"); - return null; + throw Assert.failUnchecked(ErrorCode.UNSUPPORTED_QUERY, "setting index column is not supported"); } @Override // not supported yet @ExcludeFromJacocoGeneratedReport public Identifier visitCharsetName(RelationalParser.CharsetNameContext ctx) { - Assert.failUnchecked(ErrorCode.UNSUPPORTED_QUERY, "setting charset is not supported"); - return null; + throw Assert.failUnchecked(ErrorCode.UNSUPPORTED_QUERY, "setting charset is not supported"); } @Override // not supported yet @ExcludeFromJacocoGeneratedReport public Identifier visitCollationName(RelationalParser.CollationNameContext ctx) { - Assert.failUnchecked(ErrorCode.UNSUPPORTED_QUERY, "setting collation is not supported"); - return null; + throw Assert.failUnchecked(ErrorCode.UNSUPPORTED_QUERY, "setting collation is not supported"); } @Override diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/QueryVisitor.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/QueryVisitor.java index 573b40e0e64..0a9d64f860c 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/QueryVisitor.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/QueryVisitor.java @@ -67,6 +67,7 @@ import org.antlr.v4.runtime.ParserRuleContext; import org.jspecify.annotations.Nullable; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -696,7 +697,8 @@ public LogicalOperator visitInlineTableItem(RelationalParser.InlineTableItemCont type = type == null ? rowExpression.getUnderlying().getResultType() : Type.maximumType(type, rowExpression.getUnderlying().getResultType()); } - final var actualInlineTableType = type; + // the isEmpty() check above guarantees the loop below runs at least once, so type is always assigned. + final var actualInlineTableType = Objects.requireNonNull(type, "inline table must have at least one row to infer a type"); final var inlineTypedWithNames = TypeUtils.setFieldNames(actualInlineTableType, typeMaybe.getRight()); Assert.thatUnchecked(inlineTypedWithNames.isRecord()); final var stateBuilder = LogicalPlanFragment.State.newBuilder().withTargetType(inlineTypedWithNames); @@ -770,7 +772,10 @@ private static StringTrieNode toString(CompatibleTypeEvolutionPredicate.FieldAcc if (fieldAccessTrieNode.getChildrenMap() == null) { return StringTrieNode.leafNode(); } - final var map = fieldAccessTrieNode.getChildrenMap().entrySet().stream().collect(ImmutableMap.toImmutableMap(pair -> pair.getKey().getName(), pair -> toString(pair.getValue()))); + // pair.getKey() is always constructed from an Identifier's name (see ExpressionVisitor#visitUidListWithNestings), + // which is never null, even though ResolvedAccessor.getName() is declared @Nullable in general. + final var map = fieldAccessTrieNode.getChildrenMap().entrySet().stream().collect(ImmutableMap.toImmutableMap( + pair -> Objects.requireNonNull(pair.getKey().getName()), pair -> toString(pair.getValue()))); return new StringTrieNode(map); } @@ -818,6 +823,10 @@ public LogicalOperator visitUpdateStatement(RelationalParser.UpdateStatementCont transformMapBuilder.put(target, update); } + // tableType.getStorageName() is @Nullable in general, but a table's record type always has a storage name; + // Assert.notNullUnchecked enforces that invariant at runtime with a clear RelationalException, but + // NullAway can't see that since Assert lives in the not-yet-migrated fdb-relational-api module. + @SuppressWarnings("NullAway") final var updateExpression = new UpdateExpression(Assert.castUnchecked(updateSource.getQuantifier(), Quantifier.ForEach.class), Assert.notNullUnchecked(tableType.getStorageName(), "Update target type must have storage type name available"), Type.Record.fromFields(tableType.getFields()), // Remove the type name from the update target type to avoid clashes with the table type in the update source @@ -858,7 +867,12 @@ public LogicalOperator visitDeleteStatement(RelationalParser.DeleteStatementCont Optional whereMaybe = ctx.whereExpr() == null ? Optional.empty() : Optional.of(visitWhereExpr(ctx.whereExpr())); final var deleteSource = LogicalOperator.generateSimpleSelect(output, getDelegate().getLogicalOperators(), whereMaybe, Optional.of(tableId), ImmutableSet.of(), false); - final var deleteExpression = new DeleteExpression(Assert.castUnchecked(deleteSource.getQuantifier(), Quantifier.ForEach.class), table.getType().getStorageName()); + // table.getType().getStorageName() is @Nullable in general, but a table's record type always has a storage + // name; Assert.notNullUnchecked enforces that invariant at runtime with a clear RelationalException, but + // NullAway can't see that since Assert lives in the not-yet-migrated fdb-relational-api module. + @SuppressWarnings("NullAway") + final var deleteExpression = new DeleteExpression(Assert.castUnchecked(deleteSource.getQuantifier(), Quantifier.ForEach.class), + Assert.notNullUnchecked(table.getType().getStorageName(), "Delete target type must have storage type name available")); final var deleteQuantifier = Quantifier.forEach(Reference.initialOf(deleteExpression)); final var resultingDelete = LogicalOperator.newUnnamedOperator(Expressions.fromQuantifier(deleteQuantifier), deleteQuantifier); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingLocatableResolverStore.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingLocatableResolverStore.java index 449d97f34bb..38cc7bf96cf 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingLocatableResolverStore.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingLocatableResolverStore.java @@ -57,6 +57,7 @@ import org.jspecify.annotations.Nullable; import java.util.Map; import java.util.NoSuchElementException; +import java.util.Objects; import java.util.concurrent.CompletableFuture; @API(API.Status.EXPERIMENTAL) @@ -84,7 +85,9 @@ public Row get(Row key, Options options) throws RelationalException { String name = key.getString(1); CompletableFuture resultFuture = locatableResolver.readInTransaction(context, name); ResolverResult result = context.asyncToSync(FDBStoreTimer.Waits.WAIT_DIRECTORY_RESOLVE, resultFuture); - return result == null ? null : new MessageTuple(metaDataProvider.wrapResolverResult(name, result)); + // result is non-null in this branch, so wrapResolverResult (which only returns + // null when its result argument is null) always returns non-null here. + return result == null ? null : new MessageTuple(Objects.requireNonNull(metaDataProvider.wrapResolverResult(name, result))); } else if (metaDataProvider.getResolverStateTypeKey().equals(typeKey)) { ResolverStateProto.State state = context.asyncToSync(FDBStoreTimer.Waits.WAIT_DIRECTORY_RESOLVE, locatableResolver.loadResolverState(context)); return state == null ? null : new MessageTuple(metaDataProvider.wrapResolverState(state)); @@ -110,7 +113,13 @@ public Row getFromIndex(Index index, Row key, Options options) throws Relational if (name == null) { return null; } - return new MessageTuple(metaDataProvider.wrapInterning(name, value, null)); + // wrapInterning's metaData parameter is correctly declared @Nullable byte[]; NullAway/ + // JSpecify doesn't reliably track @Nullable on array-typed parameters for a literal + // null argument (known limitation), so suppress at this narrow declaration. + final byte[] noMetaData = null; + @SuppressWarnings("NullAway") + final MessageTuple result = new MessageTuple(metaDataProvider.wrapInterning(name, value, noMetaData)); + return result; } catch (NoSuchElementException noSuchElementException) { return null; } @@ -160,6 +169,11 @@ public boolean insert(String tableName, Message message, boolean replaceOnDuplic } // Use the meta-data hook to ensure the value is created with the specified meta-data value + // MetadataHook (extends Function, defined in the not-yet-migrated + // fdb-record-layer-core) genuinely allows returning null (see + // ResolverCreateHooks.DEFAULT_HOOK = ignore -> null), but its unannotated byte[] type + // parameter is treated as non-null; known NullAway array-type limitation. + @SuppressWarnings("NullAway") ResolverCreateHooks.MetadataHook metadataHook = ignore -> metaData; ResolverCreateHooks createHooks = new ResolverCreateHooks(ResolverCreateHooks.DEFAULT_CHECK, metadataHook); context.asyncToSync(FDBStoreTimer.Waits.WAIT_DIRECTORY_RESOLVE, locatableResolver.createInTransaction(context, name, createHooks)); @@ -224,7 +238,11 @@ public RecordCursor> scanType(RecordType type, TupleRan } else if (type.getName().equals(LocatableResolverMetaDataProvider.INTERNING_TYPE_NAME)) { return locatableResolver.scan(context, continuationBytes, scanProperties) .map(resolverKeyValue -> { - Message msg = metaDataProvider.wrapResolverResult(resolverKeyValue.getKey(), resolverKeyValue.getValue()); + // resolverKeyValue.getValue() is @Nonnull, so wrapResolverResult (which + // only returns null when its result argument is null) always returns + // non-null here. + Message msg = Objects.requireNonNull( + metaDataProvider.wrapResolverResult(resolverKeyValue.getKey(), resolverKeyValue.getValue())); return FDBStoredRecord.newBuilder(msg) .setRecordType(type) .setPrimaryKey(Tuple.from(resolverKeyValue.getKey())) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/LocatableResolverMetaDataProvider.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/LocatableResolverMetaDataProvider.java index a2a87594918..71ac6d04c79 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/LocatableResolverMetaDataProvider.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/LocatableResolverMetaDataProvider.java @@ -43,6 +43,8 @@ import java.util.List; final class LocatableResolverMetaDataProvider implements RecordMetaDataProvider { + // Lazily-initialized singleton, populated by instance() below via double-checked locking. + @Nullable private static volatile LocatableResolverMetaDataProvider memoizedInstance; static final String INTERNING_TYPE_NAME = "Interning"; @@ -129,7 +131,13 @@ Message wrapResolverResult(String key, @Nullable ResolverResult result) { if (result == null) { return null; } - return wrapInterning(key, result.getValue(), result.getMetadata()); + // ResolverResult.getMetadata() (fdb-record-layer-core) and wrapInterning's metaData + // parameter are both correctly declared @Nullable byte[]; this is a known NullAway/ + // JSpecify limitation with array-typed nullability tracking. + final var metadata = result.getMetadata(); + @SuppressWarnings("NullAway") + final Message wrapped = wrapInterning(key, result.getValue(), metadata); + return wrapped; } Message wrapResolverState(ResolverStateProto.State state) { @@ -141,15 +149,18 @@ Message wrapResolverState(ResolverStateProto.State state) { } static LocatableResolverMetaDataProvider instance() throws RelationalException { - if (memoizedInstance == null) { + LocatableResolverMetaDataProvider result = memoizedInstance; + if (result == null) { synchronized (LocatableResolverMetaDataProvider.class) { - if (memoizedInstance == null) { + result = memoizedInstance; + if (result == null) { RecordMetaData metaData = SCHEMA_TEMPLATE.toRecordMetadata(); - memoizedInstance = new LocatableResolverMetaDataProvider(metaData); + result = new LocatableResolverMetaDataProvider(metaData); + memoizedInstance = result; } } } - return memoizedInstance; + return result; } public static SchemaTemplate getSchemaTemplate() { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/StoreConfig.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/StoreConfig.java index 872c0b5b779..eae0c1a7b0e 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/StoreConfig.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/StoreConfig.java @@ -46,6 +46,7 @@ import org.jspecify.annotations.Nullable; import java.net.URI; import java.util.List; +import java.util.Objects; import java.util.zip.Deflater; @API(API.Status.EXPERIMENTAL) @@ -112,7 +113,7 @@ public static StoreConfig create(RecordLayerConfig recordLayerConfig, } catch (NoSuchDirectoryException nsde) { throw new RelationalException("Uninitialized Catalog", ErrorCode.INTERNAL_ERROR, nsde); } catch (MetaDataException mde) { - throw new RelationalException(mde.getMessage(), ErrorCode.UNDEFINED_SCHEMA, mde); + throw new RelationalException(Objects.requireNonNullElse(mde.getMessage(), mde.toString()), ErrorCode.UNDEFINED_SCHEMA, mde); } catch (RecordCoreException ex) { throw ExceptionUtil.toRelationalException(ex); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/expression/ExpressionFactoryImpl.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/expression/ExpressionFactoryImpl.java index 56bdd05322f..0238f3b76f1 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/expression/ExpressionFactoryImpl.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/expression/ExpressionFactoryImpl.java @@ -64,7 +64,12 @@ Field resolve(final DataType type, final Iterable fieldParts) { ErrorCode.INVALID_COLUMN_REFERENCE, "invalid field reference %s", fieldParts); - final var normalizedFieldPart = Assert.notNullUnchecked(SemanticAnalyzer.normalizeString(fieldPart, caseSensitive)); + // normalizeString(x, ...) only returns null when x is null (see its implementation); fieldPart is + // non-null here, so the result is always non-null too, but NullAway can't see that across the + // method call, and Assert.notNullUnchecked can't narrow it either since Assert lives in the + // not-yet-migrated fdb-relational-api module. + @SuppressWarnings("NullAway") + final String normalizedFieldPart = Assert.notNullUnchecked(SemanticAnalyzer.normalizeString(fieldPart, caseSensitive)); normalizedFieldParts.add(normalizedFieldPart); final var result = ((DataType.StructType) current) @@ -84,7 +89,12 @@ Field resolve(final DataType type, final Iterable fieldParts) { @Override public Field field(final String tableName, Iterable parts) { final boolean caseSensitive = options.getOption(Options.Name.CASE_SENSITIVE_IDENTIFIERS); - final var normalizedName = Assert.notNullUnchecked(SemanticAnalyzer.normalizeString(tableName, caseSensitive)); + // normalizeString(x, ...) only returns null when x is null (see its implementation); tableName is + // non-null here, so the result is always non-null too, but NullAway can't see that across the + // method call, and Assert.notNullUnchecked can't narrow it either since Assert lives in the + // not-yet-migrated fdb-relational-api module. + @SuppressWarnings("NullAway") + final String normalizedName = Assert.notNullUnchecked(SemanticAnalyzer.normalizeString(tableName, caseSensitive)); final Optional
maybeTable; try { maybeTable = schemaTemplate.findTableByName(normalizedName); // could be a performance hit. diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/statement/UpdateStatementImpl.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/statement/UpdateStatementImpl.java index 425b84051dc..92c451e8c25 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/statement/UpdateStatementImpl.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/structuredsql/statement/UpdateStatementImpl.java @@ -205,6 +205,10 @@ public static class BuilderImpl implements UpdateStatement.Builder { private final boolean isCaseSensitive; + // table and originalTableName are populated together by setTable(...) below, and build() (further + // down) validates that setTable(...) was called before construction completes, so NullAway cannot + // see that they are always set before use. + @SuppressWarnings("NullAway.Init") public BuilderImpl(final RelationalConnection connection, final SchemaTemplate schemaTemplate) { this.connection = connection; @@ -284,7 +288,12 @@ public String getTable() { @Override public Builder setTable(final String table) { - final var normalizedTableName = + // normalizeString(x, ...) only returns null when x is null (see its implementation); table is + // non-null here, so the result is always non-null too, but NullAway can't see that across the + // method call, and Assert.notNullUnchecked can't narrow it either since Assert lives in the + // not-yet-migrated fdb-relational-api module. + @SuppressWarnings("NullAway") + final String normalizedTableName = Assert.notNullUnchecked(SemanticAnalyzer.normalizeString(table, isCaseSensitive)); Optional
maybeTable; try { @@ -495,8 +504,14 @@ private static final class UidReplacer extends RelationalParserBaseVisitor private UidReplacer(final Map> symnonymsMap, boolean isCaseSensitive) { ImmutableMap.Builder> normalizedSynonymsMap = ImmutableMap.builder(); for (final var synonymsPair : symnonymsMap.entrySet()) { - final var normalizedKey = Assert.notNullUnchecked(SemanticAnalyzer.normalizeString(synonymsPair.getKey(), isCaseSensitive)); - final var normalizedValue = synonymsPair.getValue().stream().map(part -> Assert.notNullUnchecked(SemanticAnalyzer.normalizeString(part, isCaseSensitive))).collect(Collectors.toUnmodifiableList()); + // normalizeString(x, ...) only returns null when x is null (see its implementation); the + // map key/values here are non-null, so the results are always non-null too, but NullAway + // can't see that across the method call, and Assert.notNullUnchecked can't narrow it + // either since Assert lives in the not-yet-migrated fdb-relational-api module. + @SuppressWarnings("NullAway") + final String normalizedKey = Assert.notNullUnchecked(SemanticAnalyzer.normalizeString(synonymsPair.getKey(), isCaseSensitive)); + @SuppressWarnings("NullAway") + final List normalizedValue = synonymsPair.getValue().stream().map(part -> Assert.notNullUnchecked(SemanticAnalyzer.normalizeString(part, isCaseSensitive))).collect(Collectors.toUnmodifiableList()); normalizedSynonymsMap.put(normalizedKey, normalizedValue); } this.synonymsMap = normalizedSynonymsMap.build(); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/ExceptionUtil.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/ExceptionUtil.java index 5180705e0f1..6f9cd7bf2c1 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/ExceptionUtil.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/ExceptionUtil.java @@ -37,6 +37,7 @@ import java.sql.SQLException; import java.util.Map; +import java.util.Objects; @API(API.Status.EXPERIMENTAL) public final class ExceptionUtil { @@ -44,13 +45,13 @@ public static RelationalException toRelationalException(Throwable re) { if (re instanceof RelationalException) { return (RelationalException) re; } else if (re instanceof SQLException) { - return new RelationalException(re.getMessage(), ErrorCode.get(((SQLException) re).getSQLState()), re); + return new RelationalException(Objects.requireNonNullElse(re.getMessage(), re.toString()), ErrorCode.get(((SQLException) re).getSQLState()), re); } else if (re instanceof RecordCoreException) { return recordCoreToRelationalException((RecordCoreException) re); } else if (re instanceof UncheckedRelationalException) { return ((UncheckedRelationalException) re).unwrap(); } else if (re instanceof VerifyException) { - return new RelationalException(re.getMessage(), ErrorCode.INTERNAL_ERROR, re); + return new RelationalException(Objects.requireNonNullElse(re.getMessage(), re.toString()), ErrorCode.INTERNAL_ERROR, re); } return new RelationalException(ErrorCode.UNKNOWN, re); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/Hex.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/Hex.java index ee8b14fff81..53b8a2ae444 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/Hex.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/Hex.java @@ -29,6 +29,7 @@ import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.util.Objects; /** * Converts hexadecimal Strings. @@ -360,7 +361,7 @@ public Object decode(final Object object) throws RelationalException { try { return decodeHex((char[]) object); } catch (final ClassCastException e) { - throw new RelationalException(e.getMessage(), ErrorCode.INVALID_BINARY_REPRESENTATION, e); + throw new RelationalException(Objects.requireNonNullElse(e.getMessage(), e.toString()), ErrorCode.INVALID_BINARY_REPRESENTATION, e); } } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/TypeUtils.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/TypeUtils.java index 7e904e5c8c2..56f534884f7 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/TypeUtils.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/TypeUtils.java @@ -30,6 +30,7 @@ import java.util.ArrayList; import java.util.Comparator; +import java.util.Objects; import java.util.Optional; public final class TypeUtils { @@ -51,7 +52,12 @@ private static Type setFieldNamesInternal(final Type input, } if (input.isArray()) { final var array = (Type.Array)input; - return array.withElementType(setFieldNamesInternal(Assert.notNullUnchecked(array.getElementType()), trie)); + // Assert.notNullUnchecked enforces (with a clear RelationalException) that this code path only + // ever sees non-erased arrays; NullAway can't see that since Assert lives in the not-yet-migrated + // fdb-relational-api module. + @SuppressWarnings("NullAway") + final Type elementType = Assert.notNullUnchecked(array.getElementType()); + return array.withElementType(setFieldNamesInternal(elementType, trie)); } Assert.thatUnchecked(input.isRecord(), ErrorCode.INCOMPATIBLE_TABLE_ALIAS, () -> "incompatible type found while renaming. Expected " + Type.Record.class.getSimpleName() @@ -59,14 +65,19 @@ private static Type setFieldNamesInternal(final Type input, final var record = (Type.Record)input; final var recordFields = record.getFields(); final var newlyNamedFields = ImmutableList.builder(); - final var fieldAliases = new ArrayList<>(trie.getChildrenMap().keySet()); + // A record's trie node always has a populated children map -- one entry per field -- which is + // exactly what we index into below. + final var childrenMap = Objects.requireNonNull(trie.getChildrenMap(), "record type's field-access trie node has no children map"); + final var fieldAliases = new ArrayList<>(childrenMap.keySet()); Assert.thatUnchecked(fieldAliases.size() == recordFields.size(), ErrorCode.INCOMPATIBLE_TABLE_ALIAS, () -> "number of record fields mismatch"); fieldAliases.sort(Comparator.comparingInt(FieldValue.ResolvedAccessor::getOrdinal)); for (int i = 0; i < recordFields.size(); i++) { final var fieldAlias = fieldAliases.get(i); final var recordField = recordFields.get(i); - final var fieldTrie = trie.getChildrenMap().get(fieldAlias); + // fieldAlias is one of childrenMap's own keys (drawn from childrenMap.keySet() above), so this + // lookup always finds a value. + final var fieldTrie = Objects.requireNonNull(childrenMap.get(fieldAlias)); final var renamedFieldType = setFieldNamesInternal(recordField.getFieldType(), fieldTrie); final var newField = Type.Record.Field.of(renamedFieldType, Optional.ofNullable(fieldAlias.getName()), Optional.of(recordField.getFieldIndex())); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/TransactionBoundEmbeddedRelationalEngine.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/TransactionBoundEmbeddedRelationalEngine.java index e30408eb06d..5865a16b3d2 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/TransactionBoundEmbeddedRelationalEngine.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/TransactionBoundEmbeddedRelationalEngine.java @@ -38,6 +38,7 @@ */ @API(API.Status.EXPERIMENTAL) public class TransactionBoundEmbeddedRelationalEngine extends EmbeddedRelationalEngine { + @Nullable private final RelationalPlanCache planCache; private final List clusters; @@ -79,6 +80,7 @@ public Collection getStorageClusters() { return clusters; } + @Nullable public RelationalPlanCache getPlanCache() { return planCache; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/catalog/HollowStoreCatalog.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/catalog/HollowStoreCatalog.java index 89db0d9fa07..5693fb90aca 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/catalog/HollowStoreCatalog.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/transactionbound/catalog/HollowStoreCatalog.java @@ -50,6 +50,9 @@ public HollowStoreCatalog(final SchemaTemplate schemaTemplate, @Nullable final K } @Override + @SuppressWarnings("NullAway") // StoreCatalog#getSchemaTemplateCatalog() declares no `throws`, so unlike this + // class's other methods we cannot throw OperationUnsupportedException here; this hollow catalog genuinely has + // no schema template catalog to return, and its only caller in this configuration does not invoke this method. public SchemaTemplateCatalog getSchemaTemplateCatalog() { return null; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/NullableArrayUtils.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/NullableArrayUtils.java index 6b18b3aa133..623100a47a6 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/NullableArrayUtils.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/NullableArrayUtils.java @@ -27,6 +27,8 @@ import com.google.protobuf.Descriptors; +import java.util.Objects; + /** * A Utils class that holds logic related to nullable arrays. * Nullable Arrays are arrays that, if unset, will be NULL. @@ -82,7 +84,8 @@ public static RecordKeyExpressionProto.KeyExpression wrapArray(RecordKeyExpressi } final var typeRepositoryBuilder = TypeRepository.newBuilder(); record.defineProtoType(typeRepositoryBuilder); - final var parentDescriptor = typeRepositoryBuilder.build().getMessageDescriptor(record); + // record was just defined into typeRepositoryBuilder above, so looking it back up always succeeds. + final var parentDescriptor = Objects.requireNonNull(typeRepositoryBuilder.build().getMessageDescriptor(record)); return wrapArray(keyExpression, parentDescriptor, containsNullableArray); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/Supplier.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/Supplier.java index 504e2b30c09..648db070063 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/Supplier.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/Supplier.java @@ -23,8 +23,10 @@ import com.apple.foundationdb.relational.api.exceptions.RelationalException; +import org.jspecify.annotations.Nullable; + @FunctionalInterface -public interface Supplier { +public interface Supplier { /** * Gets a result. diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/MultiStageCacheTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/MultiStageCacheTests.java index 665f3c05e01..1abe73183b9 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/MultiStageCacheTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/MultiStageCacheTests.java @@ -520,7 +520,7 @@ public void increment(final RelationalMetric.RelationalCount count, final int va } @Override - public T clock(final RelationalMetric.RelationalEvent event, final com.apple.foundationdb.relational.util.Supplier supplier) throws com.apple.foundationdb.relational.api.exceptions.RelationalException { + public T clock(final RelationalMetric.RelationalEvent event, final com.apple.foundationdb.relational.util.Supplier supplier) throws com.apple.foundationdb.relational.api.exceptions.RelationalException { return supplier.get(); } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/NoOpMetricCollector.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/NoOpMetricCollector.java index 7088718cc45..fff26d78e4b 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/NoOpMetricCollector.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/NoOpMetricCollector.java @@ -39,7 +39,7 @@ public void increment(final RelationalMetric.RelationalCount count, final int va } @Override - public T clock(final RelationalMetric.RelationalEvent event, final Supplier supplier) throws RelationalException { + public T clock(final RelationalMetric.RelationalEvent event, final Supplier supplier) throws RelationalException { return supplier.get(); } } From 94ed01ba0372f8e615e72b2899d4b209249459ed Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Wed, 2 Sep 2026 17:14:17 -0400 Subject: [PATCH 05/42] WIP: fix NullAway errors in LogicalOperator.java and Expression.java Both use Assert.notNullUnchecked/Assert.thatUnchecked in ways NullAway can't see through (Assert lives in the not-yet-migrated fdb-relational-api module); one spot in LogicalOperator switched to Objects.requireNonNull directly since it doesn't need Assert's custom exception type. --- .../relational/recordlayer/query/Expression.java | 16 +++++++++++++--- .../recordlayer/query/LogicalOperator.java | 3 ++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Expression.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Expression.java index f3a62d7e8ca..88462f8cf41 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Expression.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Expression.java @@ -252,7 +252,11 @@ static Value pullUp(Value value, Value other, AliasMap aliasMap, CorrelationIdentifier correlationIdentifier, Set constantAliases) { // Walk the value, “offering” every sub-value for replacement in terms of the reference value. - return Assert.notNullUnchecked(value.replace( + // The replacement function below never itself returns null; Assert.notNullUnchecked can't narrow + // Value#replace(...)'s result on its own since Assert lives in the not-yet-migrated + // fdb-relational-api module. + @SuppressWarnings("NullAway") + final Value replaced = Assert.notNullUnchecked(value.replace( subExpression -> { // Match this sub-value against the reference value. final Multimap pulledUpExpressionMap = @@ -274,6 +278,7 @@ static Value pullUp(Value value, Value other, AliasMap aliasMap, return Iterables.getOnlyElement(references); } )); + return replaced; } public boolean canBeDerivedFrom(final Expression expression, @@ -297,13 +302,18 @@ public boolean canBeDerivedFrom(final Expression expression, * instead of any {@link ConstantObjectValue}s. */ public Expressions dereferenced(Literals literals) { - return Expressions.ofSingle(withUnderlying(Assert.notNullUnchecked(getUnderlying().replace(value -> { + // The replacement function below never itself returns null; Assert.notNullUnchecked can't narrow + // Value#replace(...)'s result on its own since Assert lives in the not-yet-migrated + // fdb-relational-api module. + @SuppressWarnings("NullAway") + final Value replaced = Assert.notNullUnchecked(getUnderlying().replace(value -> { if (value instanceof ConstantObjectValue) { final ConstantObjectValue constantObjectValue = (ConstantObjectValue) value; return new LiteralValue<>(constantObjectValue.getResultType(), literals.asMap().get(constantObjectValue.getConstantId())); } return value; - })))); + })); + return Expressions.ofSingle(withUnderlying(replaced)); } public Expression asHidden() { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperator.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperator.java index a74204ee100..96c34388b15 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperator.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperator.java @@ -552,9 +552,10 @@ public static LogicalOperator generateSort(LogicalOperator logicalOperator, public static LogicalOperator generateInsert(LogicalOperator insertSource, Table target) { final Type.Record targetType = Assert.castUnchecked(target, RecordLayerTable.class).getType(); + final String targetStorageName = Objects.requireNonNull(targetType.getStorageName(), "target type for insert must have set storage name"); final var insertExpression = new InsertExpression(Assert.castUnchecked(insertSource.getQuantifier(), Quantifier.ForEach.class), - Assert.notNullUnchecked(targetType.getStorageName(), "target type for insert must have set storage name"), + targetStorageName, targetType); final var resultingQuantifier = Quantifier.forEach(Reference.initialOf(insertExpression)); final var output = Expressions.fromQuantifier(resultingQuantifier); From 29a1ff0a057b24c2e0f47debe6352c1553a72128 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Thu, 3 Sep 2026 11:34:58 -0400 Subject: [PATCH 06/42] WIP: fix qualified-type @Nullable placement and MutablePlanGenerationContext ctor RecordLayerIterator.java: 'RecordCursor.NoNextReason noNextReason' needs @Nullable placed as 'RecordCursor.@Nullable NoNextReason' (type-use annotation on the simple name), not as a prefix on the whole qualified type -- the latter is a genuine javac error ("scoping construct cannot be annotated with type-use annotation"), not just a NullAway finding. MutablePlanGenerationContext.java: suppress the constructor's continuation=null assignment; NullAway/JSpecify doesn't reliably track @Nullable on array-typed (byte[]) fields even though the field is already correctly declared @Nullable. --- .../relational/recordlayer/RecordLayerIterator.java | 3 +-- .../recordlayer/query/MutablePlanGenerationContext.java | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerIterator.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerIterator.java index beae5b6569d..2093f3bfebe 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerIterator.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerIterator.java @@ -46,8 +46,7 @@ public final class RecordLayerIterator implements ResumableIterator { private RecordCursorResult result; private Continuation continuation; // null until iteration is exhausted; see fetchNextResult() and getNoNextReason() below. - @Nullable - private RecordCursor.NoNextReason noNextReason; + private RecordCursor.@Nullable NoNextReason noNextReason; private RecordLayerIterator(RecordCursor cursor, Function transform) throws RelationalException { this.recordCursor = cursor; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/MutablePlanGenerationContext.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/MutablePlanGenerationContext.java index 77f5acecfb9..d4cdc6d10de 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/MutablePlanGenerationContext.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/MutablePlanGenerationContext.java @@ -253,6 +253,10 @@ private Value processPreparedStatementParameter(@Nullable Object param, } } + // continuation is already correctly declared @Nullable byte[] above; NullAway/JSpecify does not + // reliably track @Nullable on array-typed fields (known limitation), which is why this constructor + // setting it to null is still flagged as if the field were non-null. + @SuppressWarnings("NullAway") public MutablePlanGenerationContext(PreparedParams preparedParams, PlanHashable.PlanHashMode planHashMode, String query, From 6c176951aff2d7abd441a77329abeefbe2ccf5da Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Thu, 3 Sep 2026 11:48:46 -0400 Subject: [PATCH 07/42] WIP: fix NullAway errors in QueryPlan/CopyPlan/ContinuationImpl/Plan/MessageTuple/RecordLayerIterator - Plan.java: widen T to (ProceduralPlan instantiates it with Void, whose only value is null). - ContinuationImpl.parseContinuation: add missing @Nullable on the bytes param; it already handled null internally (returns BEGIN). - MessageTuple.getObject: revert to non-@Nullable signature (overriding Row#getObject(int), which NullAway treats as implicitly @NonNull) and suppress at the method instead, since it genuinely returns null for a SQL NULL/absent field. - RecordLayerIterator.next(): use Objects.requireNonNull instead of a bare @SuppressWarnings for the fetched value, since suppressing an assignment alone doesn't stop the nullness from resurfacing at the next use (lesson learned the hard way across several files). - QueryPlan.java / CopyPlan.java: several Assert.notNull(Unchecked) cross-module-narrowing fixes, byte[]/vararg array-nullability suppressions (ArrayRow, CopyPlan's continuation field/ctor), and a requireNonNull for the schema-must-be-selected invariant. --- .../recordlayer/ContinuationImpl.java | 2 +- .../relational/recordlayer/MessageTuple.java | 6 +++- .../recordlayer/RecordLayerIterator.java | 3 +- .../recordlayer/query/CopyPlan.java | 16 +++++++-- .../relational/recordlayer/query/Plan.java | 5 ++- .../recordlayer/query/QueryPlan.java | 33 +++++++++++++++---- 6 files changed, 51 insertions(+), 14 deletions(-) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ContinuationImpl.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ContinuationImpl.java index d0fa8dd62c8..fd409f98b0f 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ContinuationImpl.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ContinuationImpl.java @@ -206,7 +206,7 @@ public static Continuation fromRecordCursorContinuation(RecordCursorContinuation * @return the deserialized continuation * @throws InvalidProtocolBufferException in case the continuation cannot be deserialized */ - public static ContinuationImpl parseContinuation(byte[] bytes) throws InvalidProtocolBufferException { + public static ContinuationImpl parseContinuation(@Nullable byte[] bytes) throws InvalidProtocolBufferException { if (bytes == null) { return BEGIN; } else { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/MessageTuple.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/MessageTuple.java index 1d4e8d28ed7..4a07ea471d7 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/MessageTuple.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/MessageTuple.java @@ -50,7 +50,11 @@ public int getNumFields() { } @Override - @Nullable + // Row#getObject(int) (fdb-relational-api, unannotated) is treated by NullAway's override check as + // implicitly @NonNull, so this can't be declared @Nullable even though it genuinely returns null below + // (representing a SQL NULL / absent field or an empty vector byte string), matching Row's actual, + // documented column-value contract. + @SuppressWarnings("NullAway") public Object getObject(int position) throws InvalidColumnReferenceException { if (position < 0 || position >= getNumFields()) { throw InvalidColumnReferenceException.getExceptionForInvalidPositionNumber(position); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerIterator.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerIterator.java index 2093f3bfebe..31df59af356 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerIterator.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerIterator.java @@ -121,8 +121,7 @@ public Row next() { try { final RecordCursorResult currentResult = fetchNextResult(); // hasNext() above (via fetchNextResult().hasNext()) is what guarantees get() is non-null here. - @SuppressWarnings("NullAway") - final T nextValue = currentResult.get(); + final T nextValue = Objects.requireNonNull(currentResult.get()); final var row = transform.apply(nextValue); // TODO(sfines,yhatem) pass the Record-Layer Continuation object as-is to avoid copying bytes around. // See the comment in fetchNextResult() above about this same @SuppressWarnings. diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java index f291bfa3de2..b98f703a1d2 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java @@ -131,7 +131,12 @@ private enum CopyType { public static CopyPlan getCopyExportAction(String path, QueryExecutionContext queryExecutionContext, boolean incrementIncarnation) { - return new CopyPlan(CopyType.EXPORT, path, incrementIncarnation, queryExecutionContext, null); + // CopyPlan's constructor already declares its continuation parameter @Nullable byte[]; NullAway/ + // JSpecify doesn't reliably track @Nullable on array-typed parameters for a literal null argument + // (known limitation). + @SuppressWarnings("NullAway") + final CopyPlan plan = new CopyPlan(CopyType.EXPORT, path, incrementIncarnation, queryExecutionContext, null); + return plan; } /** @@ -143,7 +148,10 @@ public static CopyPlan getCopyExportAction(String path, */ public static CopyPlan getCopyImportAction(String path, QueryExecutionContext queryExecutionContext) { - return new CopyPlan(CopyType.IMPORT, path, false, queryExecutionContext, null); + // See the comment in getCopyExportAction() above about this same @SuppressWarnings. + @SuppressWarnings("NullAway") + final CopyPlan plan = new CopyPlan(CopyType.IMPORT, path, false, queryExecutionContext, null); + return plan; } public static CopyPlan fromContinuation(final com.apple.foundationdb.relational.continuation.CopyPlan protobuf, @@ -156,6 +164,10 @@ public static CopyPlan fromContinuation(final com.apple.foundationdb.relational. continuation); } + // continuation is already correctly declared @Nullable byte[] above; NullAway/JSpecify does not + // reliably track @Nullable on array-typed fields (known limitation), which is why this constructor's + // assignment is still flagged as if the field were non-null. + @SuppressWarnings("NullAway") private CopyPlan(CopyType copyType, String path, boolean incrementIncarnation, diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Plan.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Plan.java index ec6a3aa7b10..8edd17f7c1e 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Plan.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Plan.java @@ -29,7 +29,10 @@ import com.apple.foundationdb.relational.api.exceptions.RelationalException; import com.apple.foundationdb.relational.api.metrics.MetricCollector; import com.apple.foundationdb.relational.api.metrics.RelationalMetric; -public abstract class Plan { + +import org.jspecify.annotations.Nullable; + +public abstract class Plan { protected final String query; diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryPlan.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryPlan.java index 95bae5fa059..1e1077b498c 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryPlan.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryPlan.java @@ -171,7 +171,12 @@ public QueryPlanConstraint getContinuationConstraint() { @Override public Type getResultType() { - return Assert.notNullUnchecked(recordQueryPlan.getResultType().getInnerType()); + // getInnerType() is @Nullable in general, but recordQueryPlan's result type here always has an + // inner type; Assert.notNullUnchecked can't narrow that since Assert lives in the not-yet-migrated + // fdb-relational-api module. + @SuppressWarnings("NullAway") + final Type innerType = Assert.notNullUnchecked(recordQueryPlan.getResultType().getInnerType()); + return innerType; } public QueryExecutionContext getQueryExecutionContext() { @@ -236,7 +241,8 @@ public RelationalResultSet executeInternal(final ExecutionContext executionConte final EmbeddedRelationalConnection conn = (EmbeddedRelationalConnection) executionContext.connection; try { - final String schemaName = conn.getSchema(); + // Executing a query plan requires a schema to already be selected on the connection. + final String schemaName = Objects.requireNonNull(conn.getSchema(), "No schema selected on connection"); try (RecordLayerSchema recordLayerSchema = conn.getRecordLayerDatabase().loadSchema(schemaName)) { final var evaluationContext = queryExecutionContext.getEvaluationContext(); final var typedEvaluationContext = EvaluationContext.forBindingsAndTypeRepository(evaluationContext.getBindings(), typeRepository); @@ -333,11 +339,16 @@ private RelationalResultSet executeExplain(ContinuationImpl parsedContinuation, DataType.StructType.Field.from("PLANNER_METRICS", plannerMetricsStructType, 5)), true); + // ArrayRow's vararg parameter type isn't @Nullable (NullAway/JSpecify doesn't reliably track + // element nullability for array/vararg-typed parameters); PLAN_SERIALIZATION_MODE is genuinely + // null when there's no compiled statement. + @SuppressWarnings("NullAway") + final Object planSerializationMode = parsedContinuation.getCompiledStatement() == null ? null : parsedContinuation.getCompiledStatement().getPlanSerializationMode(); final Struct continuationInfo = ContinuationImpl.BEGIN.equals(parsedContinuation) ? null : new ImmutableRowStruct(new ArrayRow( parsedContinuation.getExecutionState(), parsedContinuation.getVersion(), - parsedContinuation.getCompiledStatement() == null ? null : parsedContinuation.getCompiledStatement().getPlanSerializationMode(), + planSerializationMode, parsedContinuation.getPlanHash(), getSerializedPlanFromContinuation(parsedContinuation, executionContext).map(RecordQueryPlan::getComplexity).orElse(null) ), RelationalStructMetaData.of(continuationStructType)); @@ -384,13 +395,18 @@ private RelationalResultSet executeExplain(ContinuationImpl parsedContinuation, } final var plannerGraph = Objects.requireNonNull(recordQueryPlan.acceptVisitor(PlannerGraphVisitor.forExplain())); - return new IteratorResultSet(RelationalStructMetaData.of(explainStructType), Collections.singleton(new ArrayRow( + // ArrayRow's vararg parameter type isn't @Nullable (NullAway/JSpecify doesn't reliably track + // element nullability for array/vararg-typed parameters); continuationInfo and plannerMetrics + // are genuinely null in some cases (see their assignments above). + @SuppressWarnings("NullAway") + final ArrayRow explainRow = new ArrayRow( explain(), planHashSupplier.get(), PlannerGraphVisitor.exportToDot(plannerGraph), PlannerGraphVisitor.exportToGml(plannerGraph, Map.of()), continuationInfo, - plannerMetrics)).iterator(), 0); + plannerMetrics); + return new IteratorResultSet(RelationalStructMetaData.of(explainStructType), Collections.singleton(explainRow).iterator(), 0); } @SuppressWarnings("PMD.CloseResource") // cursor returned inside the ResultSet, Connection now owned by this method @@ -399,8 +415,11 @@ private RelationalResultSet executePhysicalPlan(final RecordLayerSchema recordLa final ExecutionContext executionContext, final ContinuationImpl parsedContinuation) throws RelationalException { final var connection = (EmbeddedRelationalConnection) executionContext.connection; - Type type = recordQueryPlan.getResultType().getInnerType(); - Assert.notNull(type); + // Reassign through notNull (rather than discarding its result) so the non-null check actually + // narrows the value used below; Assert.notNull can't narrow it on its own since Assert lives in + // the not-yet-migrated fdb-relational-api module. + @SuppressWarnings("NullAway") + final Type type = Assert.notNull(recordQueryPlan.getResultType().getInnerType()); Assert.that(type instanceof Type.Record, ErrorCode.INTERNAL_ERROR, "unexpected plan returning top-level result of type %s", type.getTypeCode()); final FDBRecordStoreBase fdbRecordStore = recordLayerSchema.loadStore().unwrap(FDBRecordStoreBase.class); From faa249aaf10bc2e5b05e8685cc832b1364c490cf Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Thu, 3 Sep 2026 12:07:07 -0400 Subject: [PATCH 08/42] WIP: fix remaining NullAway errors in query planning files - CopyPlan.convertDataToRow: drop the dead null-check/param -- the sole caller (via RecordLayerIterator, whose next() now guarantees a non-null fetched value) never actually passes null, matching RecordLayerStoreCatalog#transformDatabaseInfo's already-non-null style. - ProceduralPlan.executeInternal: explicitly @Nullable Void return type, since Void's only value is null. - MutablePlanGenerationContext: two array/struct prepared-statement-param methods reassign their resolved type through Objects.requireNonNull right after the try block (real invariant: resolved either from the passed-in type or from introspecting the JDBC value, in both cases non-null by the time it's used). - PlanGenerator/QueryPlan: more getMessage()-requireNonNullElse fixes, Assert.notNullUnchecked cross-module suppressions, and ArrayRow vararg-element suppressions (properly wrapping the whole ArrayRow construction this time, not just an intermediate variable -- suppressing a declaration does not stop the value from being re-flagged wherever it is used next). --- .../recordlayer/query/CopyPlan.java | 6 +---- .../query/MutablePlanGenerationContext.java | 25 +++++++++++++------ .../recordlayer/query/PlanGenerator.java | 15 +++++++---- .../recordlayer/query/ProceduralPlan.java | 5 +++- .../recordlayer/query/QueryPlan.java | 13 +++++----- 5 files changed, 39 insertions(+), 25 deletions(-) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java index b98f703a1d2..89bb239815b 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java @@ -269,15 +269,11 @@ private RelationalResultSet executeExport(ExecutionContext context) throws Relat @Nullable private static ArrayRow convertDataToRow(final ExecutionContext context, - @Nullable final DataInKeySpacePath data, + final DataInKeySpacePath data, final KeySpacePathSerializer serializer, final Map pathSchemaCache, final StoreCatalog storeCatalog, final boolean incrementIncarnation) { - if (data == null) { - return null; - } - final DataInKeySpacePath effectiveData; if (incrementIncarnation) { try { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/MutablePlanGenerationContext.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/MutablePlanGenerationContext.java index d4cdc6d10de..ae864e78de2 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/MutablePlanGenerationContext.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/MutablePlanGenerationContext.java @@ -54,6 +54,7 @@ import java.util.ArrayList; import java.util.LinkedList; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.function.Supplier; @@ -202,16 +203,21 @@ private ConstantObjectValue processPreparedStatementArrayParameter(java.sql.Arra } catch (SQLException e) { throw new RelationalException(e).toUncheckedWrappedException(); } + // resolvedType is non-null here in both cases: either type was already non-null, or it was null and + // got reassigned above. + final Array nonNullResolvedType = Objects.requireNonNull(resolvedType); if (!arrayElements.isEmpty()) { - Assert.thatUnchecked(resolvedType.equals(LiteralsUtils.resolveArrayTypeFromObjectsList(arrayElements)), - DATATYPE_MISMATCH, "Cannot convert literal to " + resolvedType); + Assert.thatUnchecked(nonNullResolvedType.equals(LiteralsUtils.resolveArrayTypeFromObjectsList(arrayElements)), + DATATYPE_MISMATCH, "Cannot convert literal to " + nonNullResolvedType); } for (int i = 0; i < arrayElements.size(); i++) { final Object o = arrayElements.get(i); - processPreparedStatementParameter(o, resolvedType.getElementType(), unnamedParameterIndex, parameterName, i); + // A resolved array parameter type always has a known element type. + final Type elementType = Objects.requireNonNull(nonNullResolvedType.getElementType()); + processPreparedStatementParameter(o, elementType, unnamedParameterIndex, parameterName, i); } finishArrayLiteral(unnamedParameterIndex, parameterName, tokenIndex); - return processComplexLiteral(tokenIndex, resolvedType); + return processComplexLiteral(tokenIndex, nonNullResolvedType); } private Value processQueryLiteralOrParameter(Type type, @@ -422,13 +428,16 @@ public Value processPreparedStatementStructParameter(Struct param, } catch (SQLException e) { throw new RelationalException(e).toUncheckedWrappedException(); } - Assert.thatUnchecked(resolvedType.getFields().size() == attributes.length); + // resolvedType is non-null here in both cases: either type was already non-null, or it was null and + // got reassigned above. + final Record nonNullResolvedType = Objects.requireNonNull(resolvedType); + Assert.thatUnchecked(nonNullResolvedType.getFields().size() == attributes.length); for (int i = 0; i < attributes.length; i++) { - processPreparedStatementParameter(attributes[i], resolvedType.getFields().get(i).getFieldType(), + processPreparedStatementParameter(attributes[i], nonNullResolvedType.getFields().get(i).getFieldType(), unnamedParameterIndex, parameterName, i); } - finishStructLiteral(resolvedType, unnamedParameterIndex, parameterName, tokenIndex); - return processComplexLiteral(tokenIndex, resolvedType); + finishStructLiteral(nonNullResolvedType, unnamedParameterIndex, parameterName, tokenIndex); + return processComplexLiteral(tokenIndex, nonNullResolvedType); } public void importAuxiliaryLiterals(final Literals auxiliaryLiterals) { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanGenerator.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanGenerator.java index 38821abb5c2..c62e4feb1bf 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanGenerator.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanGenerator.java @@ -68,6 +68,7 @@ import com.google.protobuf.InvalidProtocolBufferException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.jspecify.annotations.Nullable; import java.net.URI; import java.sql.SQLException; import java.util.Arrays; @@ -212,9 +213,9 @@ private Plan getPlanInternal(String query, KeyValueLogMessage message) throws throw uve.unwrap(); } catch (MetaDataException mde) { // we need a better way for translating error codes between record layer and Relational SQL error codes - throw new RelationalException(mde.getMessage(), ErrorCode.SYNTAX_OR_ACCESS_VIOLATION, mde); + throw new RelationalException(Objects.requireNonNullElse(mde.getMessage(), mde.toString()), ErrorCode.SYNTAX_OR_ACCESS_VIOLATION, mde); } catch (VerifyException | SemanticException ve) { - throw new RelationalException(ve.getMessage(), ErrorCode.INTERNAL_ERROR, ve); + throw new RelationalException(Objects.requireNonNullElse(ve.getMessage(), ve.toString()), ErrorCode.INTERNAL_ERROR, ve); } catch (SQLException e) { throw ExceptionUtil.toRelationalException(e); } @@ -254,10 +255,10 @@ private Plan generatePhysicalPlanForCompilableStatement(AstNormalizer.Normali .generateLogicalPlan(ast.getParseTree())); return maybePlan.optimize(planner, planContext, currentPlanHashMode); } catch (ProtoUtils.InvalidNameException ine) { - throw new RelationalException(ine.getMessage(), ErrorCode.INVALID_NAME, ine).toUncheckedWrappedException(); + throw new RelationalException(Objects.requireNonNullElse(ine.getMessage(), ine.toString()), ErrorCode.INVALID_NAME, ine).toUncheckedWrappedException(); } catch (MetaDataException mde) { // we need a better way for translating error codes between record layer and Relational SQL error codes - throw new RelationalException(mde.getMessage(), ErrorCode.SYNTAX_OR_ACCESS_VIOLATION, mde).toUncheckedWrappedException(); + throw new RelationalException(Objects.requireNonNullElse(mde.getMessage(), mde.toString()), ErrorCode.SYNTAX_OR_ACCESS_VIOLATION, mde).toUncheckedWrappedException(); } catch (VerifyException | SemanticException ve) { throw ExceptionUtil.toRelationalException(ve).toUncheckedWrappedException(); } catch (RelationalException e) { @@ -309,7 +310,11 @@ private static QueryPlan.ContinuedPhysicalQueryPlan generatePhysicalPlanForCompi final Set validPlanHashModes, final PlanHashable.PlanHashMode currentPlanHashMode, final ContinuationImpl continuation, - final byte[] continuationProto) throws RelationalException { + @Nullable final byte[] continuationProto) throws RelationalException { + // hasCompiledStatement() (checked by the caller before this method is invoked) is exactly + // "getCompiledStatement() != null"; Assert.notNullUnchecked can't narrow that since Assert lives + // in the not-yet-migrated fdb-relational-api module. + @SuppressWarnings("NullAway") final var compiledStatement = Assert.notNullUnchecked(continuation.getCompiledStatement()); final var serializedPlanHashMode = PlanValidator.validateSerializedPlanSerializationMode(compiledStatement, validPlanHashModes); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ProceduralPlan.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ProceduralPlan.java index f4109aba8c0..09562360a6d 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ProceduralPlan.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ProceduralPlan.java @@ -28,6 +28,8 @@ import com.apple.foundationdb.relational.api.ddl.ConstantAction; import com.apple.foundationdb.relational.api.exceptions.RelationalException; import com.apple.foundationdb.relational.api.metrics.RelationalMetric; + +import org.jspecify.annotations.Nullable; import java.util.Objects; @API(API.Status.EXPERIMENTAL) @@ -52,7 +54,8 @@ public Plan optimize(CascadesPlanner planner, PlanContext planContext, } @Override - public Void executeInternal(final ExecutionContext context) throws RelationalException { + // Void's only value is null, so this genuinely always returns null. + public @Nullable Void executeInternal(final ExecutionContext context) throws RelationalException { final var metricCollector = Objects.requireNonNull(context.metricCollector); return metricCollector.clock(RelationalMetric.RelationalEvent.EXECUTE_PROCEDURAL_PLAN_ACTION, () -> { action.executeAction(context.transaction); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryPlan.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryPlan.java index 1e1077b498c..ab60518f546 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryPlan.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryPlan.java @@ -340,18 +340,19 @@ private RelationalResultSet executeExplain(ContinuationImpl parsedContinuation, true); // ArrayRow's vararg parameter type isn't @Nullable (NullAway/JSpecify doesn't reliably track - // element nullability for array/vararg-typed parameters); PLAN_SERIALIZATION_MODE is genuinely - // null when there's no compiled statement. - @SuppressWarnings("NullAway") + // element nullability for array/vararg-typed parameters); PLAN_SERIALIZATION_MODE and the plan + // complexity below are genuinely null in some cases. final Object planSerializationMode = parsedContinuation.getCompiledStatement() == null ? null : parsedContinuation.getCompiledStatement().getPlanSerializationMode(); - final Struct continuationInfo = ContinuationImpl.BEGIN.equals(parsedContinuation) ? null : - new ImmutableRowStruct(new ArrayRow( + @SuppressWarnings("NullAway") + final ArrayRow continuationRow = new ArrayRow( parsedContinuation.getExecutionState(), parsedContinuation.getVersion(), planSerializationMode, parsedContinuation.getPlanHash(), getSerializedPlanFromContinuation(parsedContinuation, executionContext).map(RecordQueryPlan::getComplexity).orElse(null) - ), RelationalStructMetaData.of(continuationStructType)); + ); + final Struct continuationInfo = ContinuationImpl.BEGIN.equals(parsedContinuation) ? null : + new ImmutableRowStruct(continuationRow, RelationalStructMetaData.of(continuationStructType)); final Struct plannerMetrics; if (plannerEventStatsMaps == null) { From b8efa2280c00c1790f43704c70a377f1d9a543e1 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Thu, 3 Sep 2026 12:09:59 -0400 Subject: [PATCH 09/42] WIP: fix leftover @Nullable annotations after removing null-returning code CopyPlan.convertDataToRow: forgot to drop the method's own @Nullable return annotation when the dead null-check/param was removed earlier. ProceduralPlan.executeInternal: revert to plain (unannotated) Void return with a method-level suppression -- NullAway still treats the plain type variable T from Plan#executeInternal as @NonNull at this override despite Plan's generic bound now allowing @Nullable Object, so @Nullable Void here is an override-compatibility violation, not a fix. --- .../relational/recordlayer/query/CopyPlan.java | 1 - .../relational/recordlayer/query/ProceduralPlan.java | 7 +++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java index 89bb239815b..31509d71e05 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java @@ -267,7 +267,6 @@ private RelationalResultSet executeExport(ExecutionContext context) throws Relat } } - @Nullable private static ArrayRow convertDataToRow(final ExecutionContext context, final DataInKeySpacePath data, final KeySpacePathSerializer serializer, diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ProceduralPlan.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ProceduralPlan.java index 09562360a6d..40425be0949 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ProceduralPlan.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ProceduralPlan.java @@ -54,8 +54,11 @@ public Plan optimize(CascadesPlanner planner, PlanContext planContext, } @Override - // Void's only value is null, so this genuinely always returns null. - public @Nullable Void executeInternal(final ExecutionContext context) throws RelationalException { + // Void's only value is null, so this genuinely always returns null; NullAway still treats the plain + // (unannotated) type variable T from Plan#executeInternal as @NonNull at this override, regardless of + // Plan's generic bound now allowing @Nullable Object, so this can't be declared @Nullable Void either. + @SuppressWarnings("NullAway") + public Void executeInternal(final ExecutionContext context) throws RelationalException { final var metricCollector = Objects.requireNonNull(context.metricCollector); return metricCollector.clock(RelationalMetric.RelationalEvent.EXECUTE_PROCEDURAL_PLAN_ACTION, () -> { action.executeAction(context.transaction); From a8176f88f79b2ba7feaefe15b0ad052c2d45ca55 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Thu, 3 Sep 2026 13:58:54 -0400 Subject: [PATCH 10/42] WIP: partial NullAway test-file fixes from parallel batch agents In-progress fixes across BasicMetadataTest, DelegatingVisitorTest, ProtobufDataBuilderTest, SchemaTemplateSerDeTests, RecordLayerStoreCatalogTestBase, BackingLocatableResolverStoreTest, OfflinePlanGenerationTest, PlanGenerationStackTest, SqlVisitorTests, ConstraintValidityTests. Committing now to avoid losing progress; some of these files/batches are not yet fully clean. --- .../api/ProtobufDataBuilderTest.java | 7 +++-- .../recordlayer/BasicMetadataTest.java | 31 ++++++++++++++++--- .../OfflinePlanGenerationTest.java | 17 ++++++++-- .../recordlayer/PlanGenerationStackTest.java | 9 +++++- .../RecordLayerStoreCatalogTestBase.java | 6 ++++ .../metadata/SchemaTemplateSerDeTests.java | 29 +++++++++++------ .../query/DelegatingVisitorTest.java | 24 ++++++++++---- .../query/cache/ConstraintValidityTests.java | 9 +++++- .../BackingLocatableResolverStoreTest.java | 15 +++++++-- .../structuredsql/SqlVisitorTests.java | 9 +++++- 10 files changed, 126 insertions(+), 30 deletions(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ProtobufDataBuilderTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ProtobufDataBuilderTest.java index bd31a6a5a1d..6fdf58d95ce 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ProtobufDataBuilderTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ProtobufDataBuilderTest.java @@ -27,6 +27,7 @@ import com.google.protobuf.Descriptors; import com.google.protobuf.JavaType; import com.google.protobuf.Message; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -59,7 +60,7 @@ private static Stream invalidFields() { ); } - private static Arguments invalidField(String name, JavaType javaType, String messageType, boolean isRepeated) { + private static Arguments invalidField(String name, JavaType javaType, @Nullable String messageType, boolean isRepeated) { DescriptorProtos.FieldDescriptorProto proto = newDescriptor(name, javaType, messageType, isRepeated); Object value; switch (javaType) { @@ -87,7 +88,7 @@ private static Arguments invalidField(String name, JavaType javaType, String mes return Arguments.of(proto, value); } - private static Arguments fieldArgs(String name, JavaType javaType, String messageType, boolean isRepeated) { + private static Arguments fieldArgs(String name, JavaType javaType, @Nullable String messageType, boolean isRepeated) { DescriptorProtos.FieldDescriptorProto proto = newDescriptor(name, javaType, messageType, isRepeated); Object value; switch (javaType) { @@ -117,7 +118,7 @@ private static Arguments fieldArgs(String name, JavaType javaType, String messag public static DescriptorProtos.FieldDescriptorProto newDescriptor(String name, JavaType javaType, - String messageType, + @Nullable String messageType, boolean isRepeated) { DescriptorProtos.FieldDescriptorProto.Builder proto = DescriptorProtos.FieldDescriptorProto.newBuilder() .setName(name); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/BasicMetadataTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/BasicMetadataTest.java index 3f67c03c991..f8c62c52815 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/BasicMetadataTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/BasicMetadataTest.java @@ -84,7 +84,10 @@ void canGetSchemasForDatabase() throws SQLException { final RelationalDatabaseMetaData metaData = dbConn.getMetaData(); Assertions.assertNotNull(metaData, "Null metadata returned"); - try (final RelationalResultSet schemas = metaData.getSchemas(database.getDatabasePath().getPath(), null)) { + // metaData.getSchemas(String, String) is RelationalDatabaseMetaData's JDBC-style method; per JDBC + // javadoc a null schemaPattern means "no filter" -- valid, intentional usage, but the unmigrated + // fdb-relational-api interface it's declared on isn't annotated to say so. + try (@SuppressWarnings("NullAway") final RelationalResultSet schemas = metaData.getSchemas(database.getDatabasePath().getPath(), null)) { Set retData = new HashSet<>(); ResultSetAssert.assertThat(schemas) .meetsForAllRows(ResultSetAssert.perRowCondition(rs -> @@ -95,6 +98,9 @@ void canGetSchemasForDatabase() throws SQLException { } @Test + // metaData.getSchemas(null, null) is deliberately exercising the null-catalog/null-schemaPattern JDBC + // contract inside a lambda; the unmigrated fdb-relational-api interface isn't annotated to allow it. + @SuppressWarnings("NullAway") void getSchemasForNullDatabaseThrowsException() throws SQLException { //TODO(bfines) remove this test when the catalog pattern is allowed to be null(TODO) final RelationalDatabaseMetaData metaData = dbConn.getMetaData(); @@ -109,7 +115,9 @@ void canGetTablesForSchema() throws SQLException { final RelationalDatabaseMetaData metaData = dbConn.getMetaData(); Assertions.assertNotNull(metaData, "Null metadata returned"); - try (final RelationalResultSet tables = metaData.getTables(database.getDatabasePath().getPath(), "TEST_SCHEMA", null, null)) { + // metaData.getTables(...) accepts null tableNamePattern/types per JDBC javadoc ("no filter"); the + // unmigrated fdb-relational-api interface it's declared on isn't annotated to say so. + try (@SuppressWarnings("NullAway") final RelationalResultSet tables = metaData.getTables(database.getDatabasePath().getPath(), "TEST_SCHEMA", null, null)) { Assertions.assertNotNull(tables, "Null tables returned"); List retTableNames = new ArrayList<>(); while (tables.next()) { @@ -120,6 +128,9 @@ void canGetTablesForSchema() throws SQLException { } @Test + // metaData.getTables(...) is invoked with null tableNamePattern/types inside a lambda, per the JDBC + // "no filter" contract; the unmigrated fdb-relational-api interface isn't annotated to allow it. + @SuppressWarnings("NullAway") void getTablesForMissingSchemaThrowsException() throws SQLException { final RelationalDatabaseMetaData metaData = dbConn.getMetaData(); Assertions.assertNotNull(metaData, "Null metadata returned"); @@ -133,7 +144,9 @@ void canGetTableColumns() throws SQLException { final RelationalDatabaseMetaData metaData = dbConn.getMetaData(); Assertions.assertNotNull(metaData, "Null metadata returned"); - try (final RelationalResultSet tableData = metaData.getColumns(database.getDatabasePath().getPath(), "TEST_SCHEMA", "RESTAURANT", null)) { + // metaData.getColumns(...) accepts a null columnNamePattern per JDBC javadoc ("no filter"); the + // unmigrated fdb-relational-api interface it's declared on isn't annotated to say so. + try (@SuppressWarnings("NullAway") final RelationalResultSet tableData = metaData.getColumns(database.getDatabasePath().getPath(), "TEST_SCHEMA", "RESTAURANT", null)) { List rows = new ArrayList<>(); while (tableData.next()) { rows.add(new Tuple() @@ -187,7 +200,9 @@ void getSchemasNoActiveTransaction() throws SQLException { RelationalDatabaseMetaData metaData = dbConn.getMetaData(); dbConn.setAutoCommit(false); dbConn.commit(); - try (RelationalResultSet schemas = metaData.getSchemas(dbConn.getCatalog(), null)) { + // metaData.getSchemas(...) accepts a null schemaPattern per JDBC javadoc ("no filter"); the + // unmigrated fdb-relational-api interface it's declared on isn't annotated to say so. + try (@SuppressWarnings("NullAway") RelationalResultSet schemas = metaData.getSchemas(dbConn.getCatalog(), null)) { schemas.next(); assertThat(schemas.getString("TABLE_CATALOG")).isEqualTo(database.getDatabasePath().getPath()); assertThat(schemas.getString("TABLE_SCHEM")).satisfiesAnyOf( @@ -198,6 +213,10 @@ void getSchemasNoActiveTransaction() throws SQLException { } @Test + // metaData.getTables(...) is deliberately called with null catalog/schema/table/types arguments inside + // lambdas, per the JDBC "no filter" contract; the unmigrated fdb-relational-api interface isn't + // annotated to allow it. + @SuppressWarnings("NullAway") void notSupportedGetTables() throws SQLException { RelationalDatabaseMetaData metaData = dbConn.getMetaData(); RelationalAssertions.assertThrowsSqlException( @@ -212,6 +231,10 @@ void notSupportedGetTables() throws SQLException { } @Test + // metaData.getColumns(...) is deliberately called with null catalog/schema/table/column arguments inside + // lambdas, per the JDBC "no filter" contract; the unmigrated fdb-relational-api interface isn't + // annotated to allow it. + @SuppressWarnings("NullAway") void notSupportedGetColumns() throws SQLException { RelationalDatabaseMetaData metaData = dbConn.getMetaData(); RelationalAssertions.assertThrowsSqlException( diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/OfflinePlanGenerationTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/OfflinePlanGenerationTest.java index 30e49b303e7..efda3afa3d4 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/OfflinePlanGenerationTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/OfflinePlanGenerationTest.java @@ -36,6 +36,7 @@ import com.apple.foundationdb.relational.recordlayer.query.QueryPlan; import com.apple.foundationdb.relational.recordlayer.query.cache.NoOpMetricCollector; import com.apple.foundationdb.relational.recordlayer.query.cache.RelationalPlanCache; +import com.apple.foundationdb.relational.util.Assert; import com.apple.foundationdb.relational.utils.SimpleDatabaseRule; import com.apple.foundationdb.relational.utils.TestSchemas; import org.junit.jupiter.api.BeforeEach; @@ -168,10 +169,16 @@ void offlinePlanCompareOpenStorePlan() throws Exception { final FDBRecordStoreBase store = rlDatabase.loadSchema(connection.getSchema()) .loadStore().unwrap(FDBRecordStoreBase.class); + // embeddedConnection.getMetricCollector() is @Nullable only because the collector isn't set up + // until a transaction is active (already the case here); Assert.notNullUnchecked enforces that + // invariant at runtime, but NullAway can't see that since Assert lives in the not-yet-migrated + // fdb-relational-api module. + @SuppressWarnings("NullAway") + final var metricCollector = Assert.notNullUnchecked(embeddedConnection.getMetricCollector()); final PlanContext openPlanContext = PlanContext.Builder.create() .fromRecordStore(store, options) .fromDatabase(rlDatabase) - .withMetricsCollector(embeddedConnection.getMetricCollector()) + .withMetricsCollector(metricCollector) .withSchemaTemplate(embeddedConnection.getSchemaTemplate()) .build(); final var openPlan = (QueryPlan.PhysicalQueryPlan) PlanGenerator @@ -205,10 +212,16 @@ void offlinePlanCacheForOpenStore() throws Exception { final FDBRecordStoreBase store = rlDatabase.loadSchema(connection.getSchema()) .loadStore().unwrap(FDBRecordStoreBase.class); + // embeddedConnection.getMetricCollector() is @Nullable only because the collector isn't set up + // until a transaction is active (already the case here); Assert.notNullUnchecked enforces that + // invariant at runtime, but NullAway can't see that since Assert lives in the not-yet-migrated + // fdb-relational-api module. + @SuppressWarnings("NullAway") + final var metricCollector = Assert.notNullUnchecked(embeddedConnection.getMetricCollector()); final PlanContext openPlanContext = PlanContext.Builder.create() .fromRecordStore(store, options) .fromDatabase(rlDatabase) - .withMetricsCollector(embeddedConnection.getMetricCollector()) + .withMetricsCollector(metricCollector) .withSchemaTemplate(embeddedConnection.getSchemaTemplate()) .build(); PlanGenerator.create(Optional.of(cache), openPlanContext, store, options) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/PlanGenerationStackTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/PlanGenerationStackTest.java index 9901a1302de..597734f7e38 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/PlanGenerationStackTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/PlanGenerationStackTest.java @@ -27,6 +27,7 @@ import com.apple.foundationdb.relational.recordlayer.query.PlanContext; import com.apple.foundationdb.relational.recordlayer.query.PlanGenerator; import com.apple.foundationdb.relational.recordlayer.query.QueryPlan; +import com.apple.foundationdb.relational.util.Assert; import com.apple.foundationdb.relational.utils.SimpleDatabaseRule; import com.apple.foundationdb.relational.utils.TestSchemas; import org.junit.jupiter.api.Assertions; @@ -179,12 +180,18 @@ void queryTestHarness(int ignored, String query, @Nullable String error) throws embeddedConnection.createNewTransaction(); final AbstractDatabase database = embeddedConnection.getRecordLayerDatabase(); final FDBRecordStoreBase store = database.loadSchema(schemaName).loadStore().unwrap(FDBRecordStoreBase.class); + // embeddedConnection.getMetricCollector() is @Nullable only because the collector isn't set up + // until a transaction is active (already the case here); Assert.notNullUnchecked enforces that + // invariant at runtime, but NullAway can't see that since Assert lives in the not-yet-migrated + // fdb-relational-api module. + @SuppressWarnings("NullAway") + final var metricCollector = Assert.notNullUnchecked(embeddedConnection.getMetricCollector()); final PlanContext planContext = PlanContext.Builder .create() .fromDatabase(database) .fromRecordStore(store, connection.getOptions()) .withSchemaTemplate(embeddedConnection.getSchemaTemplate()) - .withMetricsCollector(embeddedConnection.getMetricCollector()) + .withMetricsCollector(metricCollector) .build(); if (error == null) { PlanGenerator planGenerator = PlanGenerator.create(Optional.empty(), planContext, store, Options.NONE); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalogTestBase.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalogTestBase.java index 51218010a4b..3eeb831f39f 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalogTestBase.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalogTestBase.java @@ -55,6 +55,9 @@ public abstract class RecordLayerStoreCatalogTestBase { KeySpace keySpace; + // fdb and storeCatalog are initialized by subclasses' @BeforeEach methods (e.g. + // RecordLayerStoreCatalogImplTest.setUpCatalog()), not by this constructor. + @SuppressWarnings("NullAway.Init") RecordLayerStoreCatalogTestBase() { final RelationalKeyspaceProvider keyspaceProvider = RelationalKeyspaceProvider.instance(); keyspaceProvider.registerDomainIfNotExists("TEST"); @@ -306,6 +309,9 @@ static RecordLayerSchemaTemplate generateTestSchemaTemplate(final String schemaT return generateTestSchemaTemplate(schemaTemplateName, version, false); } + // The view compiler lambdas below intentionally return null (views are never actually compiled in these + // tests), but Function.apply() is assumed @NonNull. + @SuppressWarnings("NullAway") static RecordLayerSchemaTemplate generateTestSchemaTemplate(final String schemaTemplateName, int version, boolean withViews) { final var builder = RecordLayerSchemaTemplate .newBuilder() diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/SchemaTemplateSerDeTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/SchemaTemplateSerDeTests.java index 942947baf29..1d72b7eabfd 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/SchemaTemplateSerDeTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/SchemaTemplateSerDeTests.java @@ -40,6 +40,7 @@ import com.apple.foundationdb.relational.recordlayer.ddl.NoOpMetadataOperationsFactory; import com.apple.foundationdb.relational.recordlayer.metadata.serde.RecordMetadataDeserializer; import com.apple.foundationdb.relational.recordlayer.query.Literals; +import com.apple.foundationdb.relational.recordlayer.query.LogicalOperator; import com.apple.foundationdb.relational.recordlayer.query.PlanContext; import com.apple.foundationdb.relational.recordlayer.query.PlanGenerator; import com.apple.foundationdb.relational.recordlayer.query.PlannerConfiguration; @@ -67,6 +68,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.TreeMap; @@ -81,6 +83,13 @@ */ public class SchemaTemplateSerDeTests { + // Stub view compiler for tests: view expansion is not implemented yet, so it just returns null. + // RecordLayerView.Builder#setViewCompiler declares Function with a + // @NonNull result, but that class isn't in scope here, so we suppress at this single shared stub + // instead of at every one of its many call sites in this file. + @SuppressWarnings("NullAway") + private static final Function UNIMPLEMENTED_VIEW_COMPILER = ignored -> null; + @BeforeAll public static void setup() { Utils.enableCascadesDebugger(); @@ -687,7 +696,7 @@ void testViewCreationInSchemaTemplate() { .addView(RecordLayerView.newBuilder() .setName("high_salary_view") .setDescription("SELECT * FROM employees WHERE salary > 50000") - .setViewCompiler(ignored -> null) // Stub for now, view expansion not implemented + .setViewCompiler(UNIMPLEMENTED_VIEW_COMPILER) // Stub for now, view expansion not implemented .build()) .build(); @@ -715,12 +724,12 @@ void testMultipleViewsInSchemaTemplate() { .addView(RecordLayerView.newBuilder() .setName("view1") .setDescription("SELECT * FROM employees") - .setViewCompiler(ignored -> null) + .setViewCompiler(UNIMPLEMENTED_VIEW_COMPILER) .build()) .addView(RecordLayerView.newBuilder() .setName("view2") .setDescription("SELECT id FROM employees") - .setViewCompiler(ignored -> null) + .setViewCompiler(UNIMPLEMENTED_VIEW_COMPILER) .build()) .build(); @@ -746,7 +755,7 @@ void testReplaceViewInSchemaTemplate() { .addView(RecordLayerView.newBuilder() .setName("test_view") .setDescription("SELECT * FROM employees WHERE id > 10") - .setViewCompiler(ignored -> null) + .setViewCompiler(UNIMPLEMENTED_VIEW_COMPILER) .build()) .build(); @@ -755,7 +764,7 @@ void testReplaceViewInSchemaTemplate() { .replaceView(RecordLayerView.newBuilder() .setName("test_view") .setDescription("SELECT * FROM employees WHERE id > 100") - .setViewCompiler(ignored -> null) + .setViewCompiler(UNIMPLEMENTED_VIEW_COMPILER) .build()) .build(); @@ -782,7 +791,7 @@ void testRemoveViewFromSchemaTemplate() { .addView(RecordLayerView.newBuilder() .setName("test_view") .setDescription("SELECT * FROM employees") - .setViewCompiler(ignored -> null) + .setViewCompiler(UNIMPLEMENTED_VIEW_COMPILER) .build()) .build(); @@ -818,7 +827,7 @@ void testViewSerializationAndDeserialization() { .addView(RecordLayerView.newBuilder() .setName("employee_view") .setDescription("SELECT id, name FROM employees WHERE id > 100") - .setViewCompiler(ignored -> null) + .setViewCompiler(UNIMPLEMENTED_VIEW_COMPILER) .build()) .build(); @@ -869,12 +878,12 @@ void testSchemaTemplateWithTablesAndViews() { .addView(RecordLayerView.newBuilder() .setName("employee_view") .setDescription("SELECT * FROM employees") - .setViewCompiler(ignored -> null) + .setViewCompiler(UNIMPLEMENTED_VIEW_COMPILER) .build()) .addView(RecordLayerView.newBuilder() .setName("department_view") .setDescription("SELECT * FROM departments") - .setViewCompiler(ignored -> null) + .setViewCompiler(UNIMPLEMENTED_VIEW_COMPILER) .build()) .build(); @@ -893,7 +902,7 @@ void testViewBuilderToBuilder() { final var originalView = RecordLayerView.newBuilder() .setName("test_view") .setDescription("SELECT * FROM employees") - .setViewCompiler(ignored -> null) + .setViewCompiler(UNIMPLEMENTED_VIEW_COMPILER) .build(); // Convert to builder and back diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/DelegatingVisitorTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/DelegatingVisitorTest.java index a94e9a6484b..c6db5408e8b 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/DelegatingVisitorTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/DelegatingVisitorTest.java @@ -216,6 +216,7 @@ void visitViewDefinitionTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override + @SuppressWarnings("NullAway") // intentionally returns null; only the invocation is being tested here public Object visitViewDefinition(RelationalParser.ViewDefinitionContext ctx) { called.set(true); return null; @@ -231,6 +232,7 @@ void visitStoredQueryDefinitionTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override + @SuppressWarnings("NullAway") // intentionally returns null; only the invocation is being tested here public Object visitStoredQueryDefinition(RelationalParser.StoredQueryDefinitionContext ctx) { called.set(true); return null; @@ -246,6 +248,7 @@ void visitDeclareBlockTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override + @SuppressWarnings("NullAway") // intentionally returns null; only the invocation is being tested here public Object visitDeclareBlock(RelationalParser.DeclareBlockContext ctx) { called.set(true); return null; @@ -261,6 +264,7 @@ void visitDeclaredFunctionTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override + @SuppressWarnings("NullAway") // intentionally returns null; only the invocation is being tested here public Object visitDeclaredFunction(RelationalParser.DeclaredFunctionContext ctx) { called.set(true); return null; @@ -291,6 +295,7 @@ void visitIndexOptionsTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override + @SuppressWarnings("NullAway") // intentionally returns null; only the invocation is being tested here public Object visitIndexOptions(RelationalParser.IndexOptionsContext ctx) { called.set(true); return null; @@ -306,6 +311,7 @@ void visitIndexOptionTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override + @SuppressWarnings("NullAway") // intentionally returns null; only the invocation is being tested here public Object visitIndexOption(RelationalParser.IndexOptionContext ctx) { called.set(true); return null; @@ -321,6 +327,7 @@ void visitStatementOptionsTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override + @SuppressWarnings("NullAway") // intentionally returns null; only the invocation is being tested here public Object visitStatementOptions(RelationalParser.StatementOptionsContext ctx) { called.set(true); return null; @@ -336,6 +343,7 @@ void visitStatementOptionTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override + @SuppressWarnings("NullAway") // intentionally returns null; only the invocation is being tested here public Object visitStatementOption(RelationalParser.StatementOptionContext ctx) { called.set(true); return null; @@ -355,7 +363,7 @@ void visitVectorIndexDefinitionTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, query, query, 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override - @SuppressWarnings({"NullableProblems", "DataFlowIssue"}) + @SuppressWarnings({"NullableProblems", "DataFlowIssue", "NullAway"}) public RecordLayerIndex visitVectorIndexDefinition(RelationalParser.VectorIndexDefinitionContext ctx) { called.set(true); return null; @@ -375,6 +383,7 @@ void visitPartitionClauseTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, query, query, 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override + @SuppressWarnings("NullAway") // intentionally returns null; only the invocation is being tested here public Expressions visitPartitionClause(final RelationalParser.PartitionClauseContext ctx) { called.set(true); return null; @@ -390,7 +399,7 @@ void visitIndexColumnListTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override - @SuppressWarnings({"NullableProblems", "DataFlowIssue"}) + @SuppressWarnings({"NullableProblems", "DataFlowIssue", "NullAway"}) public Object visitIndexColumnList(RelationalParser.IndexColumnListContext ctx) { called.set(true); return null; @@ -406,7 +415,7 @@ void visitIncludeClauseTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override - @SuppressWarnings({"NullableProblems", "DataFlowIssue"}) + @SuppressWarnings({"NullableProblems", "DataFlowIssue", "NullAway"}) public Object visitIncludeClause(RelationalParser.IncludeClauseContext ctx) { called.set(true); return null; @@ -426,7 +435,7 @@ void visitIndexOnSourceDefinitionTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, query, query, 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override - @SuppressWarnings({"NullableProblems", "DataFlowIssue"}) + @SuppressWarnings({"NullableProblems", "DataFlowIssue", "NullAway"}) public RecordLayerIndex visitIndexOnSourceDefinition(RelationalParser.IndexOnSourceDefinitionContext ctx) { called.set(true); return null; @@ -442,6 +451,7 @@ void visitIndexTypeTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override + @SuppressWarnings("NullAway") // intentionally returns null; only the invocation is being tested here public Object visitIndexType(RelationalParser.IndexTypeContext ctx) { called.set(true); return null; @@ -457,7 +467,7 @@ void visitIndexColumnSpecTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override - @SuppressWarnings({"NullableProblems", "DataFlowIssue"}) + @SuppressWarnings({"NullableProblems", "DataFlowIssue", "NullAway"}) public Object visitIndexColumnSpec(RelationalParser.IndexColumnSpecContext ctx) { called.set(true); return null; @@ -477,7 +487,7 @@ void visitIndexAsSelectDefinitionTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, query, query, 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override - @SuppressWarnings({"NullableProblems", "DataFlowIssue"}) + @SuppressWarnings({"NullableProblems", "DataFlowIssue", "NullAway"}) public RecordLayerIndex visitIndexAsSelectDefinition(RelationalParser.IndexAsSelectDefinitionContext ctx) { called.set(true); return null; @@ -493,6 +503,7 @@ void visitOrderClauseTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override + @SuppressWarnings("NullAway") // intentionally returns null; only the invocation is being tested here public Object visitOrderClause(RelationalParser.OrderClauseContext ctx) { called.set(true); return null; @@ -508,6 +519,7 @@ void visitVectorIndexOptionsTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override + @SuppressWarnings("NullAway") // intentionally returns null; only the invocation is being tested here public Object visitVectorIndexOptions(RelationalParser.VectorIndexOptionsContext ctx) { called.set(true); return null; diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/ConstraintValidityTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/ConstraintValidityTests.java index 935db1a1362..bc694eb3474 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/ConstraintValidityTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/ConstraintValidityTests.java @@ -46,6 +46,7 @@ import com.apple.foundationdb.relational.recordlayer.query.PlanContext; import com.apple.foundationdb.relational.recordlayer.query.PlanGenerator; import com.apple.foundationdb.relational.recordlayer.query.QueryPlan; +import com.apple.foundationdb.relational.util.Assert; import com.apple.foundationdb.relational.utils.SimpleDatabaseRule; import com.apple.foundationdb.relational.utils.TestSchemas; import com.google.common.collect.ImmutableList; @@ -105,12 +106,18 @@ private PlanGenerator getPlanGenerator(final RelationalPlanCache cache) throws E final AbstractDatabase database = embeddedConnection.getRecordLayerDatabase(); final var storeState = new RecordStoreState(null, readableIndexes.stream().map(index -> Pair.of(index, IndexState.READABLE)).collect(Collectors.toMap(Pair::getKey, Pair::getValue))); final FDBRecordStoreBase store = database.loadSchema(schemaName).loadStore().unwrap(FDBRecordStoreBase.class); + // embeddedConnection.getMetricCollector() is @Nullable only because the collector isn't set up + // until a transaction is active (already the case here); Assert.notNullUnchecked enforces that + // invariant at runtime, but NullAway can't see that since Assert lives in the not-yet-migrated + // fdb-relational-api module. + @SuppressWarnings("NullAway") + final var metricCollector = Assert.notNullUnchecked(embeddedConnection.getMetricCollector()); final PlanContext planContext = PlanContext.Builder .create() .fromDatabase(database) .fromRecordStore(store, Options.none()) .withSchemaTemplate(schemaTemplate) - .withMetricsCollector(embeddedConnection.getMetricCollector()) + .withMetricsCollector(metricCollector) .build(); return PlanGenerator.create(Optional.of(cache), planContext, store.getRecordMetaData(), storeState, store.getIndexMaintainerRegistry(), Options.builder().build()); } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/storage/BackingLocatableResolverStoreTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/storage/BackingLocatableResolverStoreTest.java index 986080b688a..51f920b9f1b 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/storage/BackingLocatableResolverStoreTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/storage/BackingLocatableResolverStoreTest.java @@ -72,6 +72,7 @@ import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.Objects; import java.util.UUID; import java.util.function.Function; import java.util.stream.Collectors; @@ -92,7 +93,9 @@ public class BackingLocatableResolverStoreTest { @BeforeEach void setUp() throws RelationalException { - storageCluster = relationalExtension.getEngine() + // getEngine() is @Nullable only until the extension's own beforeEach() has run; JUnit guarantees that + // has already happened by the time this test's @BeforeEach executes. + storageCluster = Objects.requireNonNull(relationalExtension.getEngine(), "engine not initialized") .getStorageClusters() .stream() .findFirst() @@ -117,7 +120,6 @@ void tearDown() throws RelationalException { path.deleteAllData(context); context.commit(); } - path = null; } private static class TransactionBoundLocatableResolverDatabase extends AbstractDatabase { @@ -125,6 +127,8 @@ private static class TransactionBoundLocatableResolverDatabase extends AbstractD private final TransactionManager transactionManager; private final LocatableResolver resolver; private final StoreCatalog catalog; + // Never assigned outside of close(); genuinely null for the lifetime of this instance. + @Nullable private Transaction txn; public TransactionBoundLocatableResolverDatabase(URI dbPath, @@ -193,6 +197,9 @@ void basicResolve() throws RelationalException, SQLException { resolveMappings(db, 1); } + // assertMapping's byte[] metaData parameter is already @Nullable, but NullAway does not reliably + // track @Nullable on array-typed parameters. + @SuppressWarnings("NullAway") @Test void resolveMultiple() throws RelationalException, SQLException { RelationalDatabase db = createScopedInterningDatabase(); @@ -520,6 +527,10 @@ void listResolverStateWithContinuation() throws RelationalException, SQLExceptio } } + // ResolverCreateHooks.MetadataHook (fdb-relational-api, not yet migrated) extends Function; + // returning null is the documented way to signal "no metadata" (see MetadataHook.DEFAULT_HOOK), but + // NullAway does not reliably track @Nullable on array-typed return values. + @SuppressWarnings("NullAway") private Map resolveMappings(RelationalDatabase db, int count) throws RelationalException, SQLException { return resolveMappings(db, count, ignore -> null); } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/structuredsql/SqlVisitorTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/structuredsql/SqlVisitorTests.java index 028131a31c2..568eb1d4432 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/structuredsql/SqlVisitorTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/structuredsql/SqlVisitorTests.java @@ -30,6 +30,7 @@ import com.apple.foundationdb.relational.recordlayer.Utils; import com.apple.foundationdb.relational.recordlayer.query.PlanContext; import com.apple.foundationdb.relational.recordlayer.query.PlanGenerator; +import com.apple.foundationdb.relational.util.Assert; import com.apple.foundationdb.relational.utils.Ddl; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Order; @@ -169,12 +170,18 @@ private void isValidStatement(@Nonnull final RelationalConnection connection, @N embeddedConnection.createNewTransaction(); final AbstractDatabase database = embeddedConnection.getRecordLayerDatabase(); final FDBRecordStoreBase store = database.loadSchema(schemaName).loadStore().unwrap(FDBRecordStoreBase.class); + // embeddedConnection.getMetricCollector() is @Nullable only because the collector isn't set up + // until a transaction is active (already the case here); Assert.notNullUnchecked enforces that + // invariant at runtime, but NullAway can't see that since Assert lives in the not-yet-migrated + // fdb-relational-api module. + @SuppressWarnings("NullAway") + final var metricCollector = Assert.notNullUnchecked(embeddedConnection.getMetricCollector()); final PlanContext planContext = PlanContext.Builder .create() .fromDatabase(database) .fromRecordStore(store, Options.none()) .withSchemaTemplate(embeddedConnection.getSchemaTemplate()) - .withMetricsCollector(embeddedConnection.getMetricCollector()) + .withMetricsCollector(metricCollector) .build(); final PlanGenerator planGenerator = PlanGenerator.create(Optional.empty(), planContext, store, Options.NONE); Assertions.assertDoesNotThrow(() -> planGenerator.getPlan(query)); From 4275a2b369c125c15df180ba0e05dc75f4036fe0 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Thu, 3 Sep 2026 14:04:32 -0400 Subject: [PATCH 11/42] Fix NullAway errors in BasicMetadataTest and DelegatingVisitorTest - BasicMetadataTest: suppress at JDBC-null-arg call sites (getSchemas/ getTables/getColumns accept null filter params per JDBC javadoc, but the unmigrated fdb-relational-api interface isn't annotated to say so) - DelegatingVisitorTest: suppress on anonymous BaseVisitor overrides that intentionally return null (only the invocation is being asserted, not the return value) --- .../recordlayer/RelationalConnectionRule.java | 6 ++++++ .../recordlayer/RelationalStatementRule.java | 2 ++ .../metadata/SchemaTemplateSerDeTests.java | 10 ++++++---- .../recordlayer/query/DelegatingVisitorTest.java | 9 +++++++++ .../relational/recordlayer/query/UpdateTest.java | 2 +- .../query/cache/RelationalPlanCacheTests.java | 16 ++++++++++++++-- 6 files changed, 38 insertions(+), 7 deletions(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalConnectionRule.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalConnectionRule.java index 6a0a8cdbb82..58534c741c6 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalConnectionRule.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalConnectionRule.java @@ -48,6 +48,9 @@ public class RelationalConnectionRule implements BeforeEachCallback, AfterEachCa RelationalConnection connection; + // options/schema/connection are set later via the withOptions/withSchema fluent setters and + // beforeEach(), not in this constructor. + @SuppressWarnings("NullAway.Init") public RelationalConnectionRule(SqlSupplier driverSupplier, Supplier dbPathSupplier) { this.driverSupplier = driverSupplier; this.dbPathSupplier = dbPathSupplier; @@ -69,6 +72,9 @@ public RelationalConnectionRule withSchema(String schema) { } @Override + // connection is treated as non-null while the rule is active, but is reset to null here on + // teardown for test isolation between JUnit test methods. + @SuppressWarnings("NullAway") public void afterEach(ExtensionContext context) throws SQLException { if (connection != null) { connection.close(); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalStatementRule.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalStatementRule.java index 40c94c4f7e6..8c66eff492b 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalStatementRule.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalStatementRule.java @@ -40,6 +40,8 @@ public class RelationalStatementRule implements BeforeEachCallback, AfterEachCal RelationalConnection connection; RelationalStatement statement; + // statement is set later in beforeEach(), not in this constructor. + @SuppressWarnings("NullAway.Init") public RelationalStatementRule(RelationalConnection connection) { this.connection = connection; } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/SchemaTemplateSerDeTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/SchemaTemplateSerDeTests.java index 1d72b7eabfd..b328fdd5447 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/SchemaTemplateSerDeTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/SchemaTemplateSerDeTests.java @@ -249,7 +249,7 @@ void testGoodSchemaTemplateWithGenerations() { for (final var unionField : unionDesc.getFieldList()) { final var typeName = unionField.getTypeName(); Assertions.assertTrue(testcase.containsKey(typeName)); - final var expectedGenerations = testcase.get(typeName); + final var expectedGenerations = Objects.requireNonNull(testcase.get(typeName)); Assertions.assertTrue(expectedGenerations.contains(NonnullPair.of(unionField.getNumber(), unionField.getOptions()))); } } @@ -648,7 +648,7 @@ private static RecordMetadataDeserializerWithPeekingFunctionSupplier recMetadata final var functionName = entry.getKey(); final var functionDescription = entry.getValue(); Assertions.assertTrue(invokedRoutines.containsKey(functionName)); - final var function = invokedRoutines.get(functionName); + final var function = Objects.requireNonNull(invokedRoutines.get(functionName)); Assertions.assertInstanceOf(RawSqlFunction.class, function); final var rawSqlFunction = (RawSqlFunction)function; Assertions.assertEquals(functionName, rawSqlFunction.getFunctionName()); @@ -669,7 +669,9 @@ private static RecordMetadataDeserializerWithPeekingFunctionSupplier recMetadata } private static final class CompiledFunctionStub extends CompiledSqlFunction { - @SuppressWarnings("DataFlowIssue") // only for test. + // CompiledSqlFunction's "body" parameter is @NonNull, but view/function expansion isn't implemented + // for this test stub, so we intentionally pass null; CompiledSqlFunction isn't in scope to relax. + @SuppressWarnings({"DataFlowIssue", "NullAway"}) // only for test. CompiledFunctionStub() { super("something", List.of(), List.of(), List.of(), Optional.empty(), null, Literals.empty()); @@ -1053,7 +1055,7 @@ boolean hasNoCompilationRequestsFor(final String functionName) { } boolean hasOneCompilationRequestFor(final String functionName) { - return 1 == invocationsCount.get(functionName); + return Integer.valueOf(1).equals(invocationsCount.get(functionName)); } public PlanGenerator getPlanGenerator() throws RelationalException, SQLException { diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/DelegatingVisitorTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/DelegatingVisitorTest.java index c6db5408e8b..613c8d3245e 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/DelegatingVisitorTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/DelegatingVisitorTest.java @@ -535,6 +535,7 @@ void visitHnswMetricTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override + @SuppressWarnings("NullAway") // intentionally returns null; only the invocation is being tested here public Object visitHnswMetric(RelationalParser.HnswMetricContext ctx) { called.set(true); return null; @@ -550,6 +551,7 @@ void visitVectorEngineTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override + @SuppressWarnings("NullAway") // intentionally returns null; only the invocation is being tested here public Object visitVectorEngine(RelationalParser.VectorEngineContext ctx) { called.set(true); return null; @@ -565,6 +567,7 @@ void visitVectorIndexOptionValueTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override + @SuppressWarnings("NullAway") // intentionally returns null; only the invocation is being tested here public Object visitVectorIndexOptionValue(RelationalParser.VectorIndexOptionValueContext ctx) { called.set(true); return null; @@ -580,6 +583,7 @@ void visitVectorIndexOptionTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override + @SuppressWarnings("NullAway") // intentionally returns null; only the invocation is being tested here public Object visitVectorIndexOption(RelationalParser.VectorIndexOptionContext ctx) { called.set(true); return null; @@ -595,6 +599,7 @@ void visitIndexPartitionClauseTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override + @SuppressWarnings("NullAway") // intentionally returns null; only the invocation is being tested here public Object visitIndexPartitionClause(RelationalParser.IndexPartitionClauseContext ctx) { called.set(true); return null; @@ -610,6 +615,7 @@ void visitWindowOptionsClauseTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override + @SuppressWarnings("NullAway") // intentionally returns null; only the invocation is being tested here public Expressions visitWindowOptionsClause(RelationalParser.WindowOptionsClauseContext ctx) { called.set(true); return null; @@ -625,6 +631,7 @@ void visitWindowOptionTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override + @SuppressWarnings("NullAway") // intentionally returns null; only the invocation is being tested here public Expression visitWindowOption(RelationalParser.WindowOptionContext ctx) { called.set(true); return null; @@ -640,6 +647,7 @@ void visitWindowSpecTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override + @SuppressWarnings("NullAway") // intentionally returns null; only the invocation is being tested here public Object visitWindowSpec(RelationalParser.WindowSpecContext ctx) { called.set(true); return null; @@ -691,6 +699,7 @@ void visitFunctionNameKeywordTest() { called -> new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, "", "", 42), generateMetadata(), NoOpQueryFactory.INSTANCE, NoOpMetadataOperationsFactory.INSTANCE, URI.create("/FDB/FRL1"), false) { @Override + @SuppressWarnings("NullAway") // intentionally returns null; only the invocation is being tested here public Object visitFunctionNameKeyword(RelationalParser.FunctionNameKeywordContext ctx) { called.set(true); return null; diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/UpdateTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/UpdateTest.java index 33bc50b7e8f..5db42f65ff4 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/UpdateTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/UpdateTest.java @@ -20,7 +20,7 @@ package com.apple.foundationdb.relational.recordlayer.query; -import com.apple.foundationdb.record.util.pair.Pair; +import com.apple.foundationdb.record.util.pair.NonnullPair; import com.apple.foundationdb.relational.api.Continuation; import com.apple.foundationdb.relational.api.EmbeddedRelationalArray; import com.apple.foundationdb.relational.api.EmbeddedRelationalStruct; diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/RelationalPlanCacheTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/RelationalPlanCacheTests.java index f8552dd8688..061a7a057f3 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/RelationalPlanCacheTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/RelationalPlanCacheTests.java @@ -317,12 +317,18 @@ private PlanGenerator getPlanGenerator(final RelationalPlanCache cache, final AbstractDatabase database = embeddedConnection.getRecordLayerDatabase(); final var storeState = new RecordStoreState(null, readableIndexes.stream().map(index -> Pair.of(index, IndexState.READABLE)).collect(Collectors.toMap(Pair::getKey, Pair::getValue))); final FDBRecordStoreBase store = database.loadSchema(schemaName).loadStore().unwrap(FDBRecordStoreBase.class); + // embeddedConnection.getMetricCollector() is @Nullable only because the collector isn't set up + // until a transaction is active (already the case here); Assert.notNullUnchecked enforces that + // invariant at runtime, but NullAway can't see that since Assert lives in the not-yet-migrated + // fdb-relational-api module. + @SuppressWarnings("NullAway") + final var metricCollector = Assert.notNullUnchecked(embeddedConnection.getMetricCollector()); final PlanContext planContext = PlanContext.Builder .create() .fromDatabase(database) .fromRecordStore(store, options) .withSchemaTemplate(embeddedConnection.getTransaction().getBoundSchemaTemplateMaybe().orElse(schemaTemplate)) - .withMetricsCollector(Assert.notNullUnchecked(embeddedConnection.getMetricCollector())) + .withMetricsCollector(metricCollector) .withPlannerConfiguration(PlannerConfiguration.of(Optional.of(readableIndexes), options)) .build(); return PlanGenerator.create(Optional.of(cache), planContext, store.getRecordMetaData(), storeState, store.getIndexMaintainerRegistry(), options); @@ -330,8 +336,14 @@ private PlanGenerator getPlanGenerator(final RelationalPlanCache cache, private Plan.ExecutionContext getExecutionContext() throws RelationalException { final var embeddedConnection = Assert.castUnchecked(connection.getUnderlyingEmbeddedConnection(), EmbeddedRelationalConnection.class); + // embeddedConnection.getMetricCollector() is @Nullable only because the collector isn't set up + // until a transaction is active (already the case here); Assert.notNullUnchecked enforces that + // invariant at runtime, but NullAway can't see that since Assert lives in the not-yet-migrated + // fdb-relational-api module. + @SuppressWarnings("NullAway") + final var metricCollector = Assert.notNullUnchecked(embeddedConnection.getMetricCollector()); return Plan.ExecutionContext.of(embeddedConnection.getTransaction(), Options.builder().build(), - embeddedConnection, Assert.notNullUnchecked(embeddedConnection.getMetricCollector())); + embeddedConnection, metricCollector); } private static String inferScanType(final Plan plan) { From e130f18e75c86bbd06bffda11914125ffc44e8fa Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Thu, 3 Sep 2026 14:11:43 -0400 Subject: [PATCH 12/42] Fix NullAway errors in UpdateTest and StandardQueryTests - UpdateTest: switch Pair to NonnullPair since values are never actually null; suppress the two intentional updateValue.apply(null) calls where the lambda ignores its argument. - StandardQueryTests: fix a latent bug where a caught exception's message was checked with .contains(...) but the result was never asserted (partiqlAccessingNestedFieldWithInnerRepeatedFieldsFails); use Objects.requireNonNullElse for other getMessage() dereferences; switch Review.endorsements to NonnullPair since it's always constructed with literal non-null values. --- .../recordlayer/query/StandardQueryTests.java | 24 +++++++++++-------- .../recordlayer/query/UpdateTest.java | 16 ++++++++----- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/StandardQueryTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/StandardQueryTests.java index 14b143bafe6..5ec686e63ad 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/StandardQueryTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/StandardQueryTests.java @@ -24,7 +24,7 @@ import com.apple.foundationdb.linear.FloatRealVector; import com.apple.foundationdb.linear.HalfRealVector; import com.apple.foundationdb.linear.RealVector; -import com.apple.foundationdb.record.util.pair.Pair; +import com.apple.foundationdb.record.util.pair.NonnullPair; import com.apple.foundationdb.relational.api.Continuation; import com.apple.foundationdb.relational.api.EmbeddedRelationalArray; import com.apple.foundationdb.relational.api.EmbeddedRelationalStruct; @@ -67,6 +67,7 @@ import java.util.Arrays; import java.util.Base64; import java.util.List; +import java.util.Objects; import java.util.UUID; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -78,8 +79,8 @@ public class StandardQueryTests { /** * A restaurant review. */ - private record Review(long reviewer, long rating, List> endorsements) { - static Review of(long reviewer, long rating, final List> endorsements) { + private record Review(long reviewer, long rating, List> endorsements) { + static Review of(long reviewer, long rating, final List> endorsements) { return new Review(reviewer, rating, endorsements); } } @@ -675,7 +676,8 @@ void partiqlAccessingNestedFieldWithInnerRepeatedFieldsFails() throws Exception statement.execute("SELECT id, c.d.e.f, a.b.c.d.e.f FROM tbl1"); fail("expected an exception to be thrown by running 'SELECT id, c.d.e.f, a.b.c.d.e.f FROM tbl1'"); } catch (SQLException cse) { - cse.getMessage().contains("field type 'f' can only be resolved on records"); + Assertions.assertTrue(Objects.requireNonNullElse(cse.getMessage(), cse.toString()) + .contains("field type 'f' can only be resolved on records")); } } } @@ -747,11 +749,11 @@ void existsPredicateNestedWorks() throws Exception { insertRestaurantComplexRecord(statement); RelationalStruct l42 = insertRestaurantComplexRecord(statement, 42L, "rest1", List.of(Review.of(1L, 4L, List.of( - Pair.of(400L, "good"), - Pair.of(401L, "meh"))), + NonnullPair.of(400L, "good"), + NonnullPair.of(401L, "meh"))), Review.of(2L, 5L, List.of( - Pair.of(402L, "awesome"), - Pair.of(401L, "wow"))))); + NonnullPair.of(402L, "awesome"), + NonnullPair.of(401L, "wow"))))); try (final RelationalResultSet resultSet = statement.executeQuery("SELECT * FROM RestaurantComplexRecord AS R WHERE EXISTS (SELECT * FROM R.reviews AS RE WHERE EXISTS(SELECT * FROM RE.endorsements AS REE WHERE REE.\"endorsementText\"='wow'))")) { ResultSetAssert.assertThat(resultSet).containsRowsPartly(l42); } @@ -913,7 +915,8 @@ void testIncorrectUserDefinedFunction() throws Exception { try (var ddl = Ddl.builder().database(URI.create("/TEST/QT")).relationalExtension(relationalExtension).schemaTemplate(schemaTemplate3).build()) { try (var ps = ddl.setSchemaAndGetConnection().prepareStatement("SELECT * FROM T1 WHERE name(loc) = ?name")) { ps.setString("name", "Apple Park Visitor Center"); - final var errorMsg3 = Assertions.assertThrows(SQLException.class, ps::executeQuery).getMessage(); + final var exception3 = Assertions.assertThrows(SQLException.class, ps::executeQuery); + final var errorMsg3 = Objects.requireNonNullElse(exception3.getMessage(), exception3.toString()); Assertions.assertTrue(errorMsg3.contains("syntax error")); } } @@ -1223,7 +1226,8 @@ void testNamingStructsDifferentTypesThrows() throws Exception { try (var ddl = Ddl.builder().database(URI.create("/TEST/QT")).relationalExtension(relationalExtension).schemaTemplate(schemaTemplate).build()) { try (var statement = ddl.setSchemaAndGetConnection().createStatement()) { statement.executeUpdate("insert into t1 values (42, 100, 500, 101)"); - final var message = Assertions.assertThrows(SQLException.class, () -> statement.execute("select struct asd (a, 42, struct def (b, c), struct def(b, c, a)) as X from t1")).getMessage(); + final var exception = Assertions.assertThrows(SQLException.class, () -> statement.execute("select struct asd (a, 42, struct def (b, c), struct def(b, c, a)) as X from t1")); + final var message = Objects.requireNonNullElse(exception.getMessage(), exception.toString()); Assertions.assertTrue(message.contains("Name DEF is already registered with a different type")); // we could improve this error message. } } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/UpdateTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/UpdateTest.java index 5db42f65ff4..cea0d3e77e2 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/UpdateTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/UpdateTest.java @@ -81,6 +81,8 @@ public void beforeEach() throws SQLException, RelationalException { void updateSimpleFieldWithContinuationTest() throws Exception { final var fieldToUpdate = "name"; final Function updateValue = conn -> "blahText"; + // updateValue ignores its argument here, so passing null is safe even though Function.apply() requires @NonNull. + @SuppressWarnings("NullAway") final var expectedValue = updateValue.apply(null); testUpdateWithContinuationInternal(fieldToUpdate, updateValue, expectedValue); } @@ -89,6 +91,8 @@ void updateSimpleFieldWithContinuationTest() throws Exception { void updateSimpleFieldVerifyCacheTest() throws Exception { final var fieldToUpdate = "name"; final Function updateValue = conn -> "blahText"; + // updateValue ignores its argument here, so passing null is safe even though Function.apply() requires @NonNull. + @SuppressWarnings("NullAway") final var expectedValue = updateValue.apply(null); testUpdateVerifyCacheInternal(fieldToUpdate, updateValue, expectedValue); } @@ -209,18 +213,18 @@ private void verifyUpdates(String updatedField, Object expectedValue, int update } } - private Pair updateWithScanRowLimit(final String fieldToUpdate, final Function updateValue, + private NonnullPair updateWithScanRowLimit(final String fieldToUpdate, final Function updateValue, Object expectedValue) throws SQLException, RelationalException { return updateWithScanRowLimit(fieldToUpdate, updateValue, expectedValue, Options.NONE); } - private Pair updateWithScanRowLimit(final String fieldToUpdate, final Function updateValue, + private NonnullPair updateWithScanRowLimit(final String fieldToUpdate, final Function updateValue, Object expectedValue, Options options) throws SQLException, RelationalException { - return updateWithScanRowLimit(fieldToUpdate, updateValue, expectedValue, Pair.of(ContinuationImpl.BEGIN, 0), options); + return updateWithScanRowLimit(fieldToUpdate, updateValue, expectedValue, NonnullPair.of(ContinuationImpl.BEGIN, 0), options); } - private Pair updateWithScanRowLimit(final String fieldToUpdate, final Function updateValue, - Object expectedValue, Pair continuationAndNumUpdated, + private NonnullPair updateWithScanRowLimit(final String fieldToUpdate, final Function updateValue, + Object expectedValue, NonnullPair continuationAndNumUpdated, Options options) throws SQLException, RelationalException { var continuation = continuationAndNumUpdated.getLeft(); var updatedUpTill = continuationAndNumUpdated.getRight(); @@ -241,7 +245,7 @@ private Pair updateWithScanRowLimit(final String fieldToU } } } - return Pair.of(continuation, updatedUpTill); + return NonnullPair.of(continuation, updatedUpTill); } private void testUpdateWithContinuationInternal(String fieldToUpdate, Function updateValue, Object expectedValue) From 27712eefe3ae7d3b4990734c76902305c4634738 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Thu, 3 Sep 2026 14:11:45 -0400 Subject: [PATCH 13/42] WIP: fix NullAway errors in AutoCommitTests, TransactionBoundDatabaseTest, ExpressionTests --- .../relational/recordlayer/AutoCommitTests.java | 8 ++++++-- .../recordlayer/TransactionBoundDatabaseTest.java | 8 ++++++-- .../recordlayer/structuredsql/ExpressionTests.java | 11 +++++++++-- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/AutoCommitTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/AutoCommitTests.java index 26e136ad5ff..110f1bfda8c 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/AutoCommitTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/AutoCommitTests.java @@ -460,8 +460,12 @@ public void catalogMetadata(TransactionType transactionType) throws SQLException conn = getConnectionWithExistingTransaction(conn, database.getConnectionUri(), alternateDriver); } setAutoCommit(conn, transactionType); - try (final var rs = conn.getMetaData().getTables("/TEST/AutoCommitTests", "TEST_SCHEMA", null, null)) { - ResultSetAssert.assertThat(rs) + // getTables' tableNamePattern/types params genuinely accept null per the JDBC javadoc contract + // (null means "match all"), but the unmigrated fdb-relational-api interface isn't annotated to say so. + @SuppressWarnings("NullAway") + final var tables = conn.getMetaData().getTables("/TEST/AutoCommitTests", "TEST_SCHEMA", null, null); + try (tables) { + ResultSetAssert.assertThat(tables) .hasNextRow() .hasNextRow() .hasNextRow() diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/TransactionBoundDatabaseTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/TransactionBoundDatabaseTest.java index 247b347fc37..863d402397c 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/TransactionBoundDatabaseTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/TransactionBoundDatabaseTest.java @@ -67,6 +67,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.UUID; import java.util.function.Consumer; import java.util.stream.Collectors; @@ -311,7 +312,10 @@ void copyWithNullKeySpace(boolean onExport) throws SQLException, RelationalExcep RelationalAssertions.assertThrowsSqlException(() -> export.apply(statement)) .hasErrorCode(ErrorCode.UNSUPPORTED_OPERATION); } else { - data.addAll(getExportedData(export.apply(statement))); + // SQLFunction.apply() is declared @Nullable generically, but this particular + // export query always produces a result set. + final RelationalResultSet exported = Objects.requireNonNull(export.apply(statement)); + data.addAll(getExportedData(exported)); } } }); @@ -384,7 +388,7 @@ private static void withStore(final EmbeddedRelationalConnection embeddedConnect private void assertSimpleRecordExists(final FDBRecordStore store, final String field) { final FDBStoredRecord rec = store.loadRecord(Tuple.from(field)); Assertions.assertThat(rec).isNotNull(); - final Message message = rec.getRecord(); + final Message message = Objects.requireNonNull(rec).getRecord(); final Descriptors.Descriptor type = getSimpleType(store); Assertions.assertThat(message.getField(getSimpleField(type))).isEqualTo(field); } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/structuredsql/ExpressionTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/structuredsql/ExpressionTests.java index edcdc2d8e06..3353081c097 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/structuredsql/ExpressionTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/structuredsql/ExpressionTests.java @@ -66,9 +66,16 @@ public void testLiteral() { final var expressionFactory = new ExpressionFactoryImpl(sampleSchemaTemplate(), Options.NONE); Assertions.assertThat(expressionFactory.literal(false).getValue()).isEqualTo(false); Assertions.assertThat(expressionFactory.literal(true).getValue()).isEqualTo(true); - Assertions.assertThat(expressionFactory.literal((Boolean) null).getValue()).isNull(); + // ExpressionFactory#literal(Boolean)/(Integer) in the not-yet-migrated fdb-relational-api module + // are missing @Nullable on their param (inconsistent with the Long/Double/Float/String overloads, + // which do have it); null is a genuinely valid input here. + @SuppressWarnings("NullAway") + final var nullBooleanLiteral = expressionFactory.literal((Boolean) null); + Assertions.assertThat(nullBooleanLiteral.getValue()).isNull(); Assertions.assertThat(expressionFactory.literal(42).getValue()).isEqualTo(42); - Assertions.assertThat(expressionFactory.literal((Integer) null).getValue()).isNull(); + @SuppressWarnings("NullAway") + final var nullIntegerLiteral = expressionFactory.literal((Integer) null); + Assertions.assertThat(nullIntegerLiteral.getValue()).isNull(); Assertions.assertThat(expressionFactory.literal(42L).getValue()).isEqualTo(42L); Assertions.assertThat(expressionFactory.literal((Long) null).getValue()).isNull(); Assertions.assertThat(expressionFactory.literal(42.0f).getValue()).isEqualTo(42.0f); From 292bf07d0c4e1ad914deff804f04c6498c4a4d48 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Thu, 3 Sep 2026 14:17:56 -0400 Subject: [PATCH 14/42] Fix NullAway errors in KeySpacePathParsingTest, CaseSensitivityTest, ValueTupleTest, UniqueIndexTests - KeySpacePathParsingTest: add @Nullable to createDirectory()/ambiguousHalf() helper params (both already flow into constructors/methods that accept null); suppress at cross-module Pair.getLeft()/Map.get()/asyncToSync() call sites that are provably non-null in context but not annotated as such - CaseSensitivityTest: suppress at JDBC-null-arg and ArrayRow varargs call sites (unmigrated fdb-relational-api types) - ValueTupleTest: suppress testEquals() which deliberately calls equals(null) to test the equals() contract - UniqueIndexTests: fix real nullness gap -- Throwable.getMessage() can return null; use Objects.requireNonNullElse(..., e.toString()) before calling .contains() --- .../recordlayer/CaseSensitivityTest.java | 15 +++++++- .../recordlayer/KeySpacePathParsingTest.java | 38 +++++++++++++++---- .../recordlayer/UniqueIndexTests.java | 3 +- .../recordlayer/ValueTupleTest.java | 3 ++ 4 files changed, 48 insertions(+), 11 deletions(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CaseSensitivityTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CaseSensitivityTest.java index 918b6bb1679..33b1b0bfaea 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CaseSensitivityTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CaseSensitivityTest.java @@ -221,7 +221,14 @@ public void variousTables(boolean quoted) throws Exception { } RelationalDatabaseMetaData md = conn.getMetaData().unwrap(RelationalDatabaseMetaData.class); for (String table : tables) { - try (RelationalResultSet rs = md.getTables("/TEST/VARIOUS_TABLES_DB", "VARIOUS_TABLE_" + table.toUpperCase(Locale.ROOT), null, null)) { + // md.getTables(...) accepts null tableNamePattern/types per JDBC javadoc ("no filter"); the + // unmigrated fdb-relational-api interface it's declared on isn't annotated to say so. + @SuppressWarnings("NullAway") + RelationalResultSet rs = md.getTables("/TEST/VARIOUS_TABLES_DB", "VARIOUS_TABLE_" + table.toUpperCase(Locale.ROOT), null, null); + try (rs) { + // ArrayRow(Object...) is declared in the unmigrated fdb-relational-api module without + // @Nullable on its varargs elements, but a null column value is a legitimate row value. + @SuppressWarnings("NullAway") List row = List.of(new ArrayRow( "/TEST/VARIOUS_TABLES_DB", "VARIOUS_TABLE_" + table.toUpperCase(Locale.ROOT), @@ -263,7 +270,11 @@ public void variousColumns(boolean quoted) throws Exception { } RelationalDatabaseMetaData md = conn.getMetaData().unwrap(RelationalDatabaseMetaData.class); for (String column : columns) { - try (RelationalResultSet rs = md.getColumns("/TEST/VARIOUS_COLUMNS_DB", "VARIOUS_COLUMNS_" + column.toUpperCase(Locale.ROOT), "TBL_VARIOUS_COLUMNS", null)) { + // md.getColumns(...) accepts a null columnNamePattern per JDBC javadoc ("no filter"); the + // unmigrated fdb-relational-api interface it's declared on isn't annotated to say so. + @SuppressWarnings("NullAway") + RelationalResultSet rs = md.getColumns("/TEST/VARIOUS_COLUMNS_DB", "VARIOUS_COLUMNS_" + column.toUpperCase(Locale.ROOT), "TBL_VARIOUS_COLUMNS", null); + try (rs) { ResultSetAssert.assertThat(rs) .hasNextRow() .hasColumn("COLUMN_NAME", quoted ? column : column.toUpperCase(Locale.ROOT)); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/KeySpacePathParsingTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/KeySpacePathParsingTest.java index 56aa1071058..850442893bf 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/KeySpacePathParsingTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/KeySpacePathParsingTest.java @@ -28,6 +28,7 @@ import com.apple.foundationdb.record.provider.foundationdb.keyspace.KeySpace; import com.apple.foundationdb.record.provider.foundationdb.keyspace.KeySpaceDirectory; import com.apple.foundationdb.record.provider.foundationdb.keyspace.KeySpacePath; +import com.apple.foundationdb.record.provider.foundationdb.keyspace.PathValue; import com.apple.foundationdb.record.util.pair.Pair; import com.apple.foundationdb.relational.api.exceptions.ErrorCode; import com.apple.foundationdb.relational.api.exceptions.RelationalException; @@ -221,6 +222,9 @@ private static Stream> defaultValueSourc @ParameterizedTest @MethodSource("defaultValueSource") void defaultValue(Pair typeAndDefault) throws RelationalException { + // Pair.getLeft()/getRight() are declared @Nullable per their API contract, but defaultValueSource() + // never supplies a null KeyType here. + @SuppressWarnings("NullAway") KeySpace keySpace = new KeySpace( new KeySpaceDirectory("testRoot", KeySpaceDirectory.KeyType.STRING) .addSubdirectory(new KeySpaceDirectory("a", typeAndDefault.getLeft(), typeAndDefault.getRight()))); @@ -246,7 +250,13 @@ void defaultValueDirectoryLayer() throws RelationalException { static Stream unsupportedType() { return Arrays.stream(KeySpaceDirectory.KeyType.values()) .filter(type -> !PARSEABLE_KEY_TYPES.contains(type)) - .map(type -> Arguments.of(type, VALUES_FOR_TYPE.get(type).get(0))); + .map(type -> { + // VALUES_FOR_TYPE covers every KeyType (verified by validateValuesForTypeCoverage()); + // Map.get() is @Nullable per NullAway's built-in model, but the key is always present here. + @SuppressWarnings("NullAway") + final List entries = VALUES_FOR_TYPE.get(type); + return Arguments.of(type, entries.get(0)); + }); } @ParameterizedTest @@ -265,9 +275,15 @@ void unsupportedType(KeySpaceDirectory.KeyType type, PathEntry entry) { static Stream supportedType() { return Arrays.stream(KeySpaceDirectory.KeyType.values()) .filter(PARSEABLE_KEY_TYPES::contains) - .flatMap(type -> ParameterizedTestUtils.booleans("constant") - .flatMap(constant -> VALUES_FOR_TYPE.get(type).stream() - .map(pathEntry -> Arguments.of(type, constant, pathEntry)))); + .flatMap(type -> { + // VALUES_FOR_TYPE covers every KeyType (verified by validateValuesForTypeCoverage()); + // Map.get() is @Nullable per NullAway's built-in model, but the key is always present here. + @SuppressWarnings("NullAway") + final List entries = VALUES_FOR_TYPE.get(type); + return ParameterizedTestUtils.booleans("constant") + .flatMap(constant -> entries.stream() + .map(pathEntry -> Arguments.of(type, constant, pathEntry))); + }); } @ParameterizedTest @@ -538,7 +554,7 @@ private static KeySpaceDirectory createDirectoryLayerDirectory(String name, fina } private static KeySpaceDirectory createDirectory(String name, KeySpaceDirectory.KeyType type, - boolean constant, Object constantValue) { + boolean constant, @Nullable Object constantValue) { if (constant) { return new KeySpaceDirectory(name, type, constantValue); } else { @@ -585,10 +601,16 @@ private List getResolvedValuesForKeySpacePath(KeySpacePath path, FDBReco try { List values = new ArrayList<>(); KeySpacePath currentPath = path; - values.add(context.asyncToSync(FDBStoreTimer.Waits.WAIT_KEYSPACE_PATH_RESOLVE, currentPath.resolveAsync(context)).getResolvedValue()); + // asyncToSync()'s generic return type isn't nullability-annotated in this unmigrated + // record-layer-core API, but resolveAsync() never completes with a null PathValue. + @SuppressWarnings("NullAway") + PathValue resolved = context.asyncToSync(FDBStoreTimer.Waits.WAIT_KEYSPACE_PATH_RESOLVE, currentPath.resolveAsync(context)); + values.add(resolved.getResolvedValue()); while (currentPath.getParent() != null) { currentPath = currentPath.getParent(); - values.add(context.asyncToSync(FDBStoreTimer.Waits.WAIT_KEYSPACE_PATH_RESOLVE, currentPath.resolveAsync(context)).getResolvedValue()); + @SuppressWarnings("NullAway") + PathValue resolvedParent = context.asyncToSync(FDBStoreTimer.Waits.WAIT_KEYSPACE_PATH_RESOLVE, currentPath.resolveAsync(context)); + values.add(resolvedParent.getResolvedValue()); } return values; } catch (RecordCoreException ex) { @@ -620,7 +642,7 @@ private static AmbiguousHalf directoryAmbiguousHalf(String value) { path -> path.add(name, value)); } - static AmbiguousHalf ambiguousHalf(final KeySpaceDirectory.KeyType type, final Object value) { + static AmbiguousHalf ambiguousHalf(final KeySpaceDirectory.KeyType type, @Nullable final Object value) { return new AmbiguousHalf(type.name(), isConstant -> createDirectory(type.name(), type, isConstant, value), keySpace -> keySpace.path(type.name(), value), path -> path.add(type.name(), value)); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/UniqueIndexTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/UniqueIndexTests.java index b906c3ea3cc..f3ca74261b8 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/UniqueIndexTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/UniqueIndexTests.java @@ -36,6 +36,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; +import java.util.Objects; import java.util.UUID; public class UniqueIndexTests { @@ -91,7 +92,7 @@ private void checkErrorOnNonUniqueInsertionsToTable(List toIns Assertions.assertEquals(count, toInsert.size()); } catch (SQLException e) { Assertions.assertEquals(e.getSQLState(), ErrorCode.UNIQUE_CONSTRAINT_VIOLATION.getErrorCode()); - Assertions.assertTrue(e.getMessage().contains("Duplicate entry for unique index")); + Assertions.assertTrue(Objects.requireNonNullElse(e.getMessage(), e.toString()).contains("Duplicate entry for unique index")); foundError = true; } catch (Exception e) { Assertions.fail(String.format(Locale.ROOT, "Unexpected exception while inserting records to table %s: %s", tableName, e.getMessage())); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/ValueTupleTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/ValueTupleTest.java index 269b73f1e58..4b11ed44200 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/ValueTupleTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/ValueTupleTest.java @@ -123,6 +123,9 @@ void getArray() throws InvalidTypeException, InvalidColumnReferenceException { } @Test + // testLong.equals(null) deliberately exercises the equals()-must-accept-null contract; AbstractRow's + // equals(Object) parameter isn't annotated @Nullable even though Object.equals() requires tolerating null. + @SuppressWarnings("NullAway") void testEquals() { assertThat(testLong.equals(null)).isFalse(); assertThat(testLong.equals(5)).isFalse(); From 798a3d6f9d6107705618567a0b4bf01c3c2a5c29 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Thu, 3 Sep 2026 14:17:59 -0400 Subject: [PATCH 15/42] WIP: fix NullAway errors in QueryLoggingTest, CursorTest --- .../relational/recordlayer/CursorTest.java | 7 +++++-- .../relational/recordlayer/QueryLoggingTest.java | 15 +++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CursorTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CursorTest.java index b4968acdda7..3210e5f958f 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CursorTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CursorTest.java @@ -45,6 +45,7 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.function.BiConsumer; public class CursorTest { @@ -92,7 +93,7 @@ public void canIterateWithContinuation() throws SQLException, RelationalExceptio } } } - RelationalResultSet actualResults = new IteratorResultSet(metaData, actual.iterator(), 0); + RelationalResultSet actualResults = new IteratorResultSet(Objects.requireNonNull(metaData), actual.iterator(), 0); ResultSetAssert.assertThat(actualResults).containsRowsPartly(records.toArray(new RelationalStruct[]{})); } catch (SQLException e) { throw new RuntimeException(e); @@ -140,7 +141,9 @@ public void continuationOnEmptyCollection() throws SQLException, RelationalExcep resultSet = conn.createStatement().executeScan("RESTAURANT", new KeySet(), Options.NONE); Assertions.assertFalse(resultSet.next()); Continuation continuation = resultSet.getContinuation(); - Assertions.assertEquals(0, continuation.getExecutionState().length); + // The assertFalse(continuation.atBeginning()) below establishes that getExecutionState() + // is non-null at this point (atBeginning() is defined as getExecutionState() == null). + Assertions.assertEquals(0, Objects.requireNonNull(continuation.getExecutionState()).length); Assertions.assertTrue(continuation.atEnd()); Assertions.assertFalse(continuation.atBeginning()); Assertions.assertFalse(resultSet.next()); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/QueryLoggingTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/QueryLoggingTest.java index 5caddee9059..5640192cd22 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/QueryLoggingTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/QueryLoggingTest.java @@ -31,6 +31,7 @@ import com.apple.foundationdb.relational.recordlayer.query.AstNormalizer; import com.apple.foundationdb.relational.recordlayer.query.PlanContext; import com.apple.foundationdb.relational.recordlayer.query.PlanGenerator; +import com.apple.foundationdb.relational.util.Assert; import com.apple.foundationdb.relational.utils.SimpleDatabaseRule; import com.apple.foundationdb.relational.utils.TestSchemas; import org.apache.logging.log4j.Level; @@ -48,6 +49,7 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.List; +import java.util.Objects; /** * Testing basic query logging: plan, time, cache hits, etc. @@ -336,12 +338,21 @@ void testLogPlanHash() throws Exception { int queryHash = 0; conn.setAutoCommit(false); conn.createNewTransaction(); - try (var schema = conn.getRecordLayerDatabase().loadSchema(conn.getSchema())) { + // The schema is set via RelationalConnectionRule#withSchema("TEST_SCHEMA") above, so getSchema() + // is non-null here even though it's declared @Nullable for the general "no schema selected" case. + final var schemaName = Objects.requireNonNull(conn.getSchema()); + try (var schema = conn.getRecordLayerDatabase().loadSchema(schemaName)) { final var store = schema.loadStore().unwrap(FDBRecordStoreBase.class); + // conn.getMetricCollector() is @Nullable only because the collector isn't set up until a + // transaction is active (already the case here); Assert.notNullUnchecked enforces that + // invariant at runtime, but NullAway can't see that since Assert lives in the not-yet-migrated + // fdb-relational-api module. + @SuppressWarnings("NullAway") + final var metricCollector = Assert.notNullUnchecked(conn.getMetricCollector()); final var planContext = PlanContext.Builder.create() .fromRecordStore(store, conn.getOptions()) .fromDatabase(conn.getRecordLayerDatabase()) - .withMetricsCollector(conn.getMetricCollector()) + .withMetricsCollector(metricCollector) .withSchemaTemplate(conn.getSchemaTemplate()) .build(); queryHash = AstNormalizer.normalizeQuery(planContext, query1, false, PlanHashable.PlanHashMode.VC0).getQueryCacheKey().hashCode(); From ec39cd632c261a25ecc3fbd9a0dd215c8989c9a2 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Fri, 4 Sep 2026 11:31:24 -0400 Subject: [PATCH 16/42] WIP: more NullAway test-file fixes from parallel batch agents In-progress fixes across DdlTestUtil, AbstractRecordLayerResultSetTest, CopyCommandTest, KeyBuilderTest, RecordLayerStoreCatalogWithNoTemplateOperationsTest, StoreTimerMetricCollectorFromFDBRecordContextTest. Committing now to avoid losing progress; some of these files/batches are not yet fully clean. --- .../relational/api/ddl/DdlTestUtil.java | 27 ++++++++++++------- .../AbstractRecordLayerResultSetTest.java | 15 ++++++----- .../recordlayer/CopyCommandTest.java | 15 ++++++----- .../recordlayer/KeyBuilderTest.java | 15 +++++++++++ ...reCatalogWithNoTemplateOperationsTest.java | 1 + ...tricCollectorFromFDBRecordContextTest.java | 9 ++++--- 6 files changed, 56 insertions(+), 26 deletions(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/DdlTestUtil.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/DdlTestUtil.java index 40bae0dafbe..57e7a26ba0d 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/DdlTestUtil.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/DdlTestUtil.java @@ -46,6 +46,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -65,9 +66,13 @@ static PlanContext createVanillaPlanContext(final EmbeddedRelationalConnection c final var schemaTemplate = connection.getSchemaTemplate().unwrap(RecordLayerSchemaTemplate.class).toBuilder() .setVersion(1).setName(schemaTemplateName).build(); RecordMetaDataProto.MetaData md = schemaTemplate.toRecordMetadata().toProto(); + // Assert lives in the not-yet-migrated fdb-relational-api module and its parameters aren't + // annotated @Nullable, even though notNullUnchecked's entire purpose here is to null-check. + @SuppressWarnings("NullAway") + final var metricsCollector = Assert.notNullUnchecked(connection.getMetricCollector()); return PlanContext.Builder.create() .withMetadata(RecordMetaData.build(md)) - .withMetricsCollector(Assert.notNullUnchecked(connection.getMetricCollector())) + .withMetricsCollector(metricsCollector) .withPlannerConfiguration(PlannerConfiguration.ofAllAvailableIndexes()) .withDbUri(URI.create(databaseUri)) .withDdlQueryFactory(NoOpQueryFactory.INSTANCE) @@ -82,7 +87,9 @@ static PlanGenerator getPlanGenerator(final EmbeddedRelationalConnection embedde final String databaseUri) throws SQLException, RelationalException { final var planContext = createVanillaPlanContext(embeddedConnection, schemaTemplateName, databaseUri); final var storeState = new RecordStoreState(null, Map.of()); - try (var schema = embeddedConnection.getRecordLayerDatabase().loadSchema(embeddedConnection.getSchema())) { + // getSchema() is @Nullable in general, but is always set on the connection by this point in tests. + try (var schema = embeddedConnection.getRecordLayerDatabase().loadSchema( + Objects.requireNonNull(embeddedConnection.getSchema(), "schema not set on connection"))) { final var metadata = schema.loadStore().getRecordMetaData(); return PlanGenerator.create(Optional.empty(), planContext, metadata, storeState, IndexMaintainerFactoryRegistryImpl.instance(), Options.NONE); } @@ -112,7 +119,9 @@ static PlanGenerator getPlanGenerator(final EmbeddedRelationalConnection embedde final var planContext = PlanContext.Builder.unapply(createVanillaPlanContext(embeddedConnection, schemaTemplateName, databaseUri, preparedParams)) .withConstantActionFactory(metadataOperationsFactory).build(); final var storeState = new RecordStoreState(null, Map.of()); - try (var schema = embeddedConnection.getRecordLayerDatabase().loadSchema(embeddedConnection.getSchema())) { + // getSchema() is @Nullable in general, but is always set on the connection by this point in tests. + try (var schema = embeddedConnection.getRecordLayerDatabase().loadSchema( + Objects.requireNonNull(embeddedConnection.getSchema(), "schema not set on connection"))) { final var metadata = schema.loadStore().getRecordMetaData(); return PlanGenerator.create(Optional.empty(), planContext, metadata, storeState, IndexMaintainerFactoryRegistryImpl.instance(), options); } @@ -125,7 +134,9 @@ static PlanGenerator getPlanGenerator(final EmbeddedRelationalConnection embedde final var planContext = PlanContext.Builder.unapply(createVanillaPlanContext(embeddedConnection, schemaTemplateName, databaseUri)) .withDdlQueryFactory(ddlQueryFactory).build(); final var storeState = new RecordStoreState(null, Map.of()); - try (var schema = embeddedConnection.getRecordLayerDatabase().loadSchema(embeddedConnection.getSchema())) { + // getSchema() is @Nullable in general, but is always set on the connection by this point in tests. + try (var schema = embeddedConnection.getRecordLayerDatabase().loadSchema( + Objects.requireNonNull(embeddedConnection.getSchema(), "schema not set on connection"))) { final var metadata = schema.loadStore().getRecordMetaData(); return PlanGenerator.create(Optional.empty(), planContext, metadata, storeState, IndexMaintainerFactoryRegistryImpl.instance(), Options.NONE); } @@ -403,15 +414,13 @@ private void buildTypesAndTables() { * @param typeName the name of the type to find * @return the ParsedType if found, null otherwise */ - @SuppressWarnings("DataFlowIssue") ParsedType getType(final String typeName) { for (final ParsedType parsedType : types) { if (parsedType.getName().equals(typeName)) { return parsedType; } } - Assertions.fail("could not find type " + typeName); - return null; // not reachable. + return Assertions.fail("could not find type " + typeName); } /** @@ -420,15 +429,13 @@ ParsedType getType(final String typeName) { * @param tableName the name of the table to find * @return the ParsedType representing the table if found, null otherwise */ - @SuppressWarnings("DataFlowIssue") ParsedType getTable(final String tableName) { for (final ParsedType table : tables) { if (table.getName().equals(tableName)) { return table; } } - Assertions.fail("could not find table" + tableName); - return null; // not reachable. + return Assertions.fail("could not find table" + tableName); } } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/AbstractRecordLayerResultSetTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/AbstractRecordLayerResultSetTest.java index 8b141ff5c51..085a2edc12e 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/AbstractRecordLayerResultSetTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/AbstractRecordLayerResultSetTest.java @@ -31,6 +31,7 @@ import com.google.protobuf.DynamicMessage; import com.google.protobuf.Message; import org.assertj.core.api.Assertions; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -166,6 +167,8 @@ static Stream cannotConvertTestCases() { private Row theRow; private AbstractRecordLayerResultSet resultSet; + // theRow is assigned by each @Test method before use, not by setUp() itself. + @SuppressWarnings("NullAway.Init") @BeforeEach void setUp() throws SQLException { StructMetaData smd = Mockito.mock(StructMetaData.class); @@ -297,14 +300,14 @@ void testMethodCoherence() { private static class TestCase { String method; - Object field; + @Nullable Object field; - TestCase(String method, Object field) { + TestCase(String method, @Nullable Object field) { this.method = method; this.field = field; } - static TestCase of(String method, Object field) { + static TestCase of(String method, @Nullable Object field) { return new TestCase(method, field); } @@ -321,14 +324,14 @@ public String toString() { } private static class TestCaseWithResult extends TestCase { - Object expected; + @Nullable Object expected; - TestCaseWithResult(String method, Object field, Object expected) { + TestCaseWithResult(String method, @Nullable Object field, @Nullable Object expected) { super(method, field); this.expected = expected; } - static TestCaseWithResult of(String method, Object field, Object expected) { + static TestCaseWithResult of(String method, @Nullable Object field, @Nullable Object expected) { return new TestCaseWithResult(method, field, expected); } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CopyCommandTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CopyCommandTest.java index 7d1ef130e66..9f2ce6015b6 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CopyCommandTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CopyCommandTest.java @@ -66,6 +66,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.UUID; import java.util.function.IntFunction; import java.util.stream.Collectors; @@ -90,7 +91,7 @@ public class CopyCommandTest { @BeforeEach void setUp() { - connectionUtils = new ConnectionUtils(relationalExtension.getDriver()); + connectionUtils = new ConnectionUtils(Objects.requireNonNull(relationalExtension.getDriver())); } @ParameterizedTest @@ -148,7 +149,7 @@ void withExecutionContext(boolean withExecutionContext) throws RelationalExcepti clearTestData(connectionUtils, sourceTestPath); // Import to destination (using quoted path) - int importedCount = connectionUtils.getFromCatalog(conn -> { + int importedCount = Objects.requireNonNull(connectionUtils.getFromCatalog(conn -> { final EmbeddedRelationalConnection embeddedConnection = (EmbeddedRelationalConnection)conn; embeddedConnection.createNewTransaction(); int count; @@ -163,7 +164,7 @@ void withExecutionContext(boolean withExecutionContext) throws RelationalExcepti } final Plan.ExecutionContext executionContext = Plan.ExecutionContext.of( embeddedConnection.getTransaction(), - Options.NONE, conn, embeddedConnection.getMetricCollector()); + Options.NONE, conn, Objects.requireNonNull(embeddedConnection.getMetricCollector())); try (final RelationalResultSet relationalResultSet = copyImportAction.execute(executionContext)) { assertTrue(relationalResultSet.next()); count = relationalResultSet.getInt("COUNT"); @@ -172,7 +173,7 @@ void withExecutionContext(boolean withExecutionContext) throws RelationalExcepti } return count; - }); + })); assertEquals(withExecutionContext ? 3 : 2, importedCount); final KeySpacePath destTestPath = KeySpaceUtils.toKeySpacePath(URI.create(dest.schemaPath), keySpace); @@ -366,7 +367,7 @@ void invalidContinuationPlanHash() throws RelationalException, SQLException { assertFalse(continuation.atBeginning()); final ContinuationImpl continuationImpl = (ContinuationImpl)rs.getContinuation(); final Continuation corruptedContinuation = continuationImpl.asBuilder() - .withPlanHash(continuationImpl.getPlanHash() + 3) + .withPlanHash(Objects.requireNonNull(continuationImpl.getPlanHash()) + 3) .build(); RelationalAssertions.assertThrowsSqlException( () -> continueExport(limit, conn, corruptedContinuation, results)) @@ -529,7 +530,7 @@ void copyCatalogWithMultipleSchemas(boolean quoted, boolean multiCluster) throws String templateName1 = "TEMPLATE1_" + uuidName; String templateName2 = "TEMPLATE2_" + uuidName; final ConnectionUtils destConnectionUtils = multiCluster ? - new ConnectionUtils(relationalExtension.extensionForOtherCluster().getDriver()) : + new ConnectionUtils(Objects.requireNonNull(relationalExtension.extensionForOtherCluster().getDriver())) : connectionUtils; final List moveables = IntStream.of(0, 1, 2) .mapToObj(index -> { @@ -802,7 +803,7 @@ private static List exportData(boolean quoted, String path, ConnectionUt } private static List exportData(String path, ConnectionUtils connectionUtils, String incarnationClause) throws SQLException, RelationalException { - return connectionUtils.getFromCatalog(conn -> { + return Objects.requireNonNull(connectionUtils.getFromCatalog(conn -> { try (RelationalStatement stmt = conn.createStatement(); RelationalResultSet rs = stmt.executeQuery("COPY " + path + " " + incarnationClause)) { List exportedData = new ArrayList<>(); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/KeyBuilderTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/KeyBuilderTest.java index b038a2b4416..614dd210006 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/KeyBuilderTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/KeyBuilderTest.java @@ -37,6 +37,9 @@ class KeyBuilderTest { @Test void testEmptyKeyExpression() throws RelationalException { + // KeyBuilder#typeForKey isn't @Nullable, but it's unused by buildKey() in this test path; + // KeyBuilder itself is out of scope to annotate here. + @SuppressWarnings("NullAway") KeyBuilder keyBuilder = new KeyBuilder(null, EmptyKeyExpression.EMPTY, "empty"); Row key = keyBuilder.buildKey(Map.of(), true); assertThat(key.getNumFields()).isEqualTo(0); @@ -44,6 +47,9 @@ void testEmptyKeyExpression() throws RelationalException { @Test void testFailOnIncompleteKey() { + // KeyBuilder#typeForKey isn't @Nullable, but it's unused by buildKey() in this test path; + // KeyBuilder itself is out of scope to annotate here. + @SuppressWarnings("NullAway") KeyBuilder keyBuilder = new KeyBuilder(null, concat(field("A"), field("B")), "test"); assertThrows(() -> keyBuilder.buildKey(Map.of(), true)) .hasErrorCode(ErrorCode.INVALID_PARAMETER); @@ -53,6 +59,9 @@ void testFailOnIncompleteKey() { @Test void testFailOnMissingKeyAtPosition() { + // KeyBuilder#typeForKey isn't @Nullable, but it's unused by buildKey() in this test path; + // KeyBuilder itself is out of scope to annotate here. + @SuppressWarnings("NullAway") KeyBuilder keyBuilder = new KeyBuilder(null, concat(field("A"), field("B")), "test"); assertThrows(() -> keyBuilder.buildKey(Map.of("B", 5), false)) .hasErrorCode(ErrorCode.INVALID_PARAMETER); @@ -60,6 +69,9 @@ void testFailOnMissingKeyAtPosition() { @Test void testPartialKey() throws RelationalException { + // KeyBuilder#typeForKey isn't @Nullable, but it's unused by buildKey() in this test path; + // KeyBuilder itself is out of scope to annotate here. + @SuppressWarnings("NullAway") KeyBuilder keyBuilder = new KeyBuilder(null, concat(field("A"), field("B")), "test"); Row key = keyBuilder.buildKey(Map.of("A", 5), false); assertThat(key.getNumFields()).isEqualTo(1); @@ -68,6 +80,9 @@ void testPartialKey() throws RelationalException { @Test void testIncompleteKeyAllNulls() throws RelationalException { + // KeyBuilder#typeForKey isn't @Nullable, but it's unused by buildKey() in this test path; + // KeyBuilder itself is out of scope to annotate here. + @SuppressWarnings("NullAway") KeyBuilder keyBuilder = new KeyBuilder(null, concat(field("A"), field("B")), "test"); Row key = keyBuilder.buildKey(Map.of(), false); assertThat(key.getNumFields()).isEqualTo(0); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalogWithNoTemplateOperationsTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalogWithNoTemplateOperationsTest.java index 00f069453f4..5c0ccc97731 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalogWithNoTemplateOperationsTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalogWithNoTemplateOperationsTest.java @@ -39,6 +39,7 @@ import org.junit.jupiter.api.Test; import java.net.URI; +import java.util.Objects; public class RecordLayerStoreCatalogWithNoTemplateOperationsTest extends RecordLayerStoreCatalogTestBase { diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metric/StoreTimerMetricCollectorFromFDBRecordContextTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metric/StoreTimerMetricCollectorFromFDBRecordContextTest.java index a5b2a2ad338..c1e76cea710 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metric/StoreTimerMetricCollectorFromFDBRecordContextTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metric/StoreTimerMetricCollectorFromFDBRecordContextTest.java @@ -36,6 +36,7 @@ import java.net.URI; import java.sql.SQLException; +import java.util.Objects; import java.util.function.Consumer; public class StoreTimerMetricCollectorFromFDBRecordContextTest { @@ -68,7 +69,8 @@ void testContinuedPlanMetrics() throws Exception { resultSetAssert.hasNextRow(); } resultSetAssert.hasNoNextRow(); - var collector = connection.getMetricCollector(); + // getMetricCollector() is @Nullable in general, but is always set by the time a statement has executed. + var collector = Objects.requireNonNull(connection.getMetricCollector(), "metric collector not set"); testGeneralMetrics(collector); testExecuteContinuationSpecificMetrics(collector); } @@ -92,7 +94,8 @@ private Continuation executeSimpleSelectAndReturnContinuation(EmbeddedRelational } resultSetAssert.hasNoNextRow(); continuation = resultSet.getContinuation(); - var collector = connection.getMetricCollector(); + // getMetricCollector() is @Nullable in general, but is always set by the time a statement has executed. + var collector = Objects.requireNonNull(connection.getMetricCollector(), "metric collector not set"); testGeneralMetrics(collector); if (!hitCache) { testCacheMissSpecificMetrics(collector); @@ -103,7 +106,7 @@ private Continuation executeSimpleSelectAndReturnContinuation(EmbeddedRelational } catch (SQLException sql) { Assertions.fail(sql); } - return continuation; + return Objects.requireNonNull(continuation, "continuation should have been set unless an assertion failed above"); } private void setupAndExecuteWithConnection(Consumer execute) throws Exception { From c53caddd013ec92097807089100d37698bc8e57c Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Fri, 4 Sep 2026 11:33:26 -0400 Subject: [PATCH 17/42] WIP: fix NullAway error in RecordLayerStoreCatalogWithNoTemplateOperationsTest --- .../RecordLayerStoreCatalogWithNoTemplateOperationsTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalogWithNoTemplateOperationsTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalogWithNoTemplateOperationsTest.java index 5c0ccc97731..fcde685beff 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalogWithNoTemplateOperationsTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalogWithNoTemplateOperationsTest.java @@ -121,7 +121,7 @@ void testRepairSchema() throws RelationalException { try (Transaction txn = new RecordContextTransaction(fdb.openContext())) { final var thrown = Assertions.assertThrows(RelationalException.class, () -> storeCatalog.repairSchema(txn, schema1.getDatabaseName(), schema1.getName())); Assertions.assertEquals(ErrorCode.UNSUPPORTED_OPERATION, thrown.getErrorCode()); - Assertions.assertTrue(thrown.getMessage().contains("does not support")); + Assertions.assertTrue(Objects.requireNonNullElse(thrown.getMessage(), thrown.toString()).contains("does not support")); txn.commit(); } } From b7bf9954e329e75e35654d59c09444e9ff3fcbbf Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Fri, 4 Sep 2026 11:35:26 -0400 Subject: [PATCH 18/42] Fix NullAway errors in CopyCommandTest.java - Wrap ConnectionUtils.getFromCatalog()/EmbeddedRelationalConnection#getMetricCollector()/ EmbeddedRelationalExtension#getDriver() results with Objects.requireNonNull() at call sites, since those methods are declared @Nullable but are known non-null in these test contexts; the declaring classes are out of scope to annotate differently here. - Same treatment for ContinuationImpl#getPlanHash() unboxing. --- .../relational/recordlayer/CopyCommandTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CopyCommandTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CopyCommandTest.java index 9f2ce6015b6..1847facc131 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CopyCommandTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CopyCommandTest.java @@ -812,7 +812,7 @@ private static List exportData(String path, ConnectionUtils connectionUt } return exportedData; } - }); + })); } private static int importDatabase(final boolean namedAndQuoted, final boolean autoCommit, final SchemaInfo dest, @@ -822,7 +822,7 @@ private static int importDatabase(final boolean namedAndQuoted, final boolean au private static int importDatabase(final boolean namedAndQuoted, final boolean autoCommit, final List exportedData, ConnectionUtils targetConnectionUtils, String path) throws SQLException, RelationalException { - return targetConnectionUtils.getFromCatalog(conn -> { + return Objects.requireNonNull(targetConnectionUtils.getFromCatalog(conn -> { conn.setAutoCommit(autoCommit); int resultingCount; try (RelationalPreparedStatement stmt = conn.prepareStatement("COPY " + maybeQuote(path, namedAndQuoted) + " FROM " + (namedAndQuoted ? "?data" : "?"))) { @@ -844,7 +844,7 @@ private static int importDatabase(final boolean namedAndQuoted, final boolean au conn.commit(); } return resultingCount; - }); + })); } private static class Moveable { From 3add9279d2852653f34d19e086a130b7011f31b0 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Fri, 4 Sep 2026 11:37:22 -0400 Subject: [PATCH 19/42] WIP: fix NullAway errors in PlaceholderCatalog, InsertTest, StoredQueriesTest --- .../foundationdb/relational/recordlayer/InsertTest.java | 5 +++++ .../relational/recordlayer/PlaceholderCatalog.java | 1 + .../relational/recordlayer/query/StoredQueriesTest.java | 5 +++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/InsertTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/InsertTest.java index ec27af321d7..4f96ef1e4f7 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/InsertTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/InsertTest.java @@ -211,6 +211,11 @@ void cannotInsertDuplicatePrimaryKey() throws SQLException { } @Test + // This test intentionally passes a null element into the varargs array to exercise validation + // (addAll's Object... elements aren't @Nullable-annotated, and array element nullness isn't + // reliably tracked by NullAway); the suppression also covers the getMessage() dereference below, + // which is always non-null for the exception thrown by this code path. + @SuppressWarnings("NullAway") void canNotAddNullElementToArray() { final var builder = EmbeddedRelationalArray.newBuilder(); final var throwAssert = Assertions.assertThrows(SQLException.class, () -> builder.addAll(1, 2, 3, null, 5, 6)); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/PlaceholderCatalog.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/PlaceholderCatalog.java index caf4d967ee8..5468e6cd848 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/PlaceholderCatalog.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/PlaceholderCatalog.java @@ -65,6 +65,7 @@ public SchemaData(String name, Descriptors.FileDescriptor fileDesc, Map Date: Fri, 4 Sep 2026 11:41:35 -0400 Subject: [PATCH 20/42] WIP: fix NullAway errors in AstNormalizerTests --- .../recordlayer/query/AstNormalizerTests.java | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizerTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizerTests.java index 4db357bf5f0..8aec42d852b 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizerTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizerTests.java @@ -57,6 +57,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; @@ -264,7 +265,9 @@ private static void validate(final List queries, final var evaluationContext = execParams.getEvaluationContext(); final var constantBindingName = Bindings.Internal.CONSTANT.bindingName(Quantifier.constant().getId()); if (evaluationContext.getBindings().containsBinding(constantBindingName)) { - final var binding = evaluationContext.getBinding(constantBindingName); + // containsBinding() confirms the binding exists; getBinding() is @Nullable in general + // (a bound value could itself be null), but a CONSTANT binding is always a real map. + final var binding = Objects.requireNonNull(evaluationContext.getBinding(constantBindingName)); compareBindings(binding, expectedParameters); } else { if (!expectedParameters.isEmpty()) { @@ -403,17 +406,23 @@ private static RecordLayerSchemaTemplate schemaTemplateWithFunction(final Record .setDescription(functionDdl) .setNormalizedDescription(canonicalFunctionDdl) // invoking the compiled routine should only happen during plan generation. - .withUserDefinedFunctionProvider(ignored -> new CompiledSqlFunction("", List.of(), List.of(), - List.of(), Optional.empty(), null, Literals.empty()) { - @Override - public RecordMetaDataProto.PUserDefinedFunction toProto() { - throw new UnsupportedOperationException("unexpected call"); - } - - @Override - public RelationalExpression encapsulate(final CallSiteArguments arguments) { - throw new UnsupportedOperationException("unexpected call"); - } + .withUserDefinedFunctionProvider(ignored -> { + // body is unused in this test stub: both overrides below always throw, so the + // constructor's @NonNull body param is never dereferenced. + @SuppressWarnings("NullAway") + final CompiledSqlFunction stub = new CompiledSqlFunction("", List.of(), List.of(), + List.of(), Optional.empty(), null, Literals.empty()) { + @Override + public RecordMetaDataProto.PUserDefinedFunction toProto() { + throw new UnsupportedOperationException("unexpected call"); + } + + @Override + public RelationalExpression encapsulate(final CallSiteArguments arguments) { + throw new UnsupportedOperationException("unexpected call"); + } + }; + return stub; }) .withSerializableFunction(new RawSqlFunction(name, functionDdl)) .build()) From b721fb1b7477d14cab57f31f850248d016e0692d Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Fri, 4 Sep 2026 11:41:38 -0400 Subject: [PATCH 21/42] Fix NullAway errors in metric/cache test files and DdlTestUtil - StoreTimerMetricCollectorFromFDBRecordContextTest: use Objects.requireNonNull for getMetricCollector()/continuation, both known non-null by test invariant. - DdlTestUtil: extract Assert.notNullUnchecked result to a suppressed local (Assert lives in the not-yet-migrated fdb-relational-api module); use Objects.requireNonNull for getSchema(); replace dead "fail() then return null" with "return fail()" in ParsedSchema.getType/getTable (assertj's fail() returns T, so no unreachable null return is needed). - ConcurrentCacheTests/MultiStageCacheTests: suppress at call sites where pickFirst's @Nullable return is passed to AbstractCache.reduce()'s unannotated Function, V> parameter (main code, out of scope); removed dead/broken unused produceAnimal/produceLandform/produceCapital helpers in MultiStageCacheTests (they indexed entries by the wrong key level and were never called); extracted nested fixture-map lookups in readCache() to a small helper using Objects.requireNonNull. --- .../query/cache/ConcurrentCacheTests.java | 9 ++++++- .../query/cache/MultiStageCacheTests.java | 27 +++++++++---------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/ConcurrentCacheTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/ConcurrentCacheTests.java index 4189c33e926..6369c43443d 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/ConcurrentCacheTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/ConcurrentCacheTests.java @@ -34,6 +34,7 @@ import org.junit.jupiter.api.Test; import org.jspecify.annotations.Nullable; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Random; import java.util.concurrent.CountDownLatch; @@ -88,17 +89,23 @@ private static String generateIScan(int boundary) { return "full scan with " + boundary; } + // pickFirst intentionally returns null when the stream has no matches (mirrored by MultiStageCache's own + // null-check on the reduction result), but AbstractCache.reduce()'s Function, V> parameter type + // (main code, out of scope here) doesn't reflect that nullability. + @SuppressWarnings("NullAway") private static void getOrLoadT1lt300(final MultiStageCache cache) { final var result = cache.reduce("T1", "1", ppeFor(ecFor(300)), () -> NonnullPair.of(ppeFor(lt500Constraint), generateIScan(500)), s -> s + " overriden with 300", ConcurrentCacheTests::pickFirst, NoOpMetricCollector.INSTANCE); Assertions.assertThat(result).doesNotContain("150"); // we must not scan index <150 as the returned results would be incorrect } + @SuppressWarnings("NullAway") private static void getOrLoadT1lt90(final MultiStageCache cache) { cache.reduce("T1", "1", ppeFor(ecFor(90)), () -> NonnullPair.of(ppeFor(lt150Constraint), generateIScan(150)), s -> s + " overriden with 90", ConcurrentCacheTests::pickFirst, NoOpMetricCollector.INSTANCE); } + @SuppressWarnings("NullAway") private static void getOrLoadT1lt1000(final MultiStageCache cache) { final var result = cache.reduce("T1", "1", ppeFor(ecFor(1000)), () -> NonnullPair.of(ppeFor(lt1000Constraint), generateFullScan()), s -> s + " overriden with 1000", ConcurrentCacheTests::pickFirst, NoOpMetricCollector.INSTANCE); @@ -113,7 +120,7 @@ private static void randomWorkLoad(final MultiStageCache produceAnimal(final String k2, final String k3) { - return Pair.of(k2, entries.get("Animal").get(k2).get(k3)); - } - - private static Pair produceLandform(final String k2, final String k3) { - return Pair.of(k2, entries.get("Landform").get(k2).get(k3)); - } - - private static Pair produceCapital(final String k2, final String k3) { - return Pair.of(k2, entries.get("Capital").get(k2).get(k3)); - } - private static void shouldBe(final MultiStageCache cache, Map>> expectedLayout) { Map>> result = new HashMap<>(); for (String key : cache.getStats().getAllKeys()) { @@ -363,17 +351,28 @@ private static String readCache(MultiStageCache return readCache(cache, key, secondaryKey, tertiaryKey, NoOpMetricCollector.INSTANCE); } + // pickFirst intentionally returns null for an empty stream (AbstractCache.reduce() null-checks the result + // internally), but AbstractCache.reduce()'s Function, V> parameter type (main code, out of scope + // here) doesn't reflect that nullability. + @SuppressWarnings("NullAway") private static String readCache(MultiStageCache cache, String key, String secondaryKey, String tertiaryKey, MetricCollector metricCollector) { return cache.reduce(key, secondaryKey, tertiaryKey, - () -> NonnullPair.of(tertiaryKey, entries.get(key).get(secondaryKey).get(tertiaryKey)), + () -> NonnullPair.of(tertiaryKey, lookupFixture(key, secondaryKey, tertiaryKey)), MultiStageCacheTests::fetchFromCache, MultiStageCacheTests::pickFirst, metricCollector); } + // The (key, secondaryKey, tertiaryKey) combinations used by tests are always present in entries. + private static String lookupFixture(String key, String secondaryKey, String tertiaryKey) { + final var secondaryMap = Objects.requireNonNull(entries.get(key), () -> "unknown key " + key); + final var tertiaryMap = Objects.requireNonNull(secondaryMap.get(secondaryKey), () -> "unknown secondary key " + secondaryKey); + return Objects.requireNonNull(tertiaryMap.get(tertiaryKey), () -> "unknown tertiary key " + tertiaryKey); + } + @Test void primaryCacheLruEvictionEmitsEvent() { final var metricCollector = new CountMetricCollector(); From 2332604419e757f22985f186cc8a75718db6957f Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Fri, 4 Sep 2026 11:43:18 -0400 Subject: [PATCH 22/42] Fix NullAway errors in StructDataMetadataTest, RowStructTest, RelationalArrayTest, RecordTypeTableSerDeTest - StructDataMetadataTest: require non-null continuation before serialize() (all call sites pass numBaseQueryRuns >= 1 alongside numContinuationRuns, so it's always populated by then). - RowStructTest: suppress at the ArrayRow(null, 1L) call site -- the null vararg element is intentional, representing a SQL NULL for the wasNullWorks test; ArrayRow is out of scope. - RelationalArrayTest: mark the nullArrayElements helper parameter @Nullable since callers intentionally pass null to mean "expect a null array". - RecordTypeTableSerDeTest: require non-null on fieldData.get("A") -- "A" is the primary key column and always present and non-null across every call site. --- .../relational/recordlayer/RecordTypeTableSerDeTest.java | 3 ++- .../relational/recordlayer/RelationalArrayTest.java | 3 ++- .../foundationdb/relational/recordlayer/RowStructTest.java | 4 ++++ .../relational/recordlayer/StructDataMetadataTest.java | 5 ++++- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RecordTypeTableSerDeTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RecordTypeTableSerDeTest.java index 6236e5c0822..a2ac499e1c6 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RecordTypeTableSerDeTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RecordTypeTableSerDeTest.java @@ -33,6 +33,7 @@ import java.sql.SQLException; import java.util.Map; +import java.util.Objects; import java.util.UUID; /** @@ -63,7 +64,7 @@ private void roundTripT1(Map fieldData) throws SQLException { builder.addObject(entry.getKey(), entry.getValue()); } statement.executeInsert("T1", builder.build()); - try (RelationalResultSet getRes = statement.executeGet("T1", new KeySet().setKeyColumn("A", fieldData.get("A")), Options.NONE)) { + try (RelationalResultSet getRes = statement.executeGet("T1", new KeySet().setKeyColumn("A", Objects.requireNonNull(fieldData.get("A"))), Options.NONE)) { ResultSetAssert.assertThat(getRes) .hasNextRow() .row() diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalArrayTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalArrayTest.java index 87455210d75..361dc44ddf5 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalArrayTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalArrayTest.java @@ -30,6 +30,7 @@ import com.apple.foundationdb.relational.utils.RelationalStructAssert; import com.apple.foundationdb.relational.utils.ResultSetAssert; import com.apple.foundationdb.relational.utils.SimpleDatabaseRule; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; @@ -402,7 +403,7 @@ void testArrays(int nullArrayIdx, int nonNullArrayIdx, List filledArray, testArrays(nullArrayIdx, nonNullArrayIdx, null, filledArray, sqlType, 2); } - private void testArrays(int nullArrayIdx, int nonNullArrayIdx, List nullArrayElements, + private void testArrays(int nullArrayIdx, int nonNullArrayIdx, @Nullable List nullArrayElements, List nonNullArrayElements, int sqlType, int pk) throws SQLException { try (final var conn = DriverManager.getConnection(database.getConnectionUri().toString())) { conn.setSchema(database.getSchemaName()); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RowStructTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RowStructTest.java index abd7a491293..8eab64da588 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RowStructTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RowStructTest.java @@ -57,6 +57,10 @@ private static RowStruct createStruct(boolean mutable) { DataType.StructType.Field.from("fInt", DataType.Primitives.NULLABLE_LONG.type(), 1) ), true); final var metadata = RelationalStructMetaData.of(type); + // ArrayRow's varargs aren't @Nullable, but a null element here intentionally represents a SQL NULL + // in the first field, which is exactly what this test (wasNullWorks) exercises; ArrayRow is out of + // scope to annotate here. + @SuppressWarnings("NullAway") final var row = new ArrayRow(null, 1L); if (mutable) { final var toReturn = new MutableRowStruct(metadata); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/StructDataMetadataTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/StructDataMetadataTest.java index 898e0313d0b..227727285d2 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/StructDataMetadataTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/StructDataMetadataTest.java @@ -42,6 +42,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.Objects; import java.util.Set; import static com.apple.foundationdb.relational.utils.RelationalAssertions.assertThrowsSqlException; @@ -231,7 +232,9 @@ private void canReadStructTypeName(String query, // Run continuation the specified number of times for (int i = 0; i < numContinuationRuns; i++) { try (final PreparedStatement ps = connection.prepareStatement("EXECUTE CONTINUATION ?")) { - ps.setBytes(1, continuation.serialize()); + // Populated by the base query loop above whenever numContinuationRuns > 0 (all call sites use + // numBaseQueryRuns >= 1 together with numContinuationRuns). + ps.setBytes(1, Objects.requireNonNull(continuation).serialize()); try (final ResultSet resultSet = ps.executeQuery()) { Assertions.assertTrue(resultSet.next(), "Did not find a record on continuation run " + (i + 1)); assertOnMetaData.accept(resultSet.unwrap(RelationalResultSet.class)); From 48e2b3d5f80b9bccc34e10b554813ddbc8bbfc5e Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Fri, 4 Sep 2026 12:04:40 -0400 Subject: [PATCH 23/42] WIP: fix NullAway errors in MetricsCollectionTest, StoreTimerMetricCollectorFromMetricRegistryTest --- .../recordlayer/metric/MetricsCollectionTest.java | 6 ++++-- .../StoreTimerMetricCollectorFromMetricRegistryTest.java | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metric/MetricsCollectionTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metric/MetricsCollectionTest.java index 52f970689b5..f26a2d3a010 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metric/MetricsCollectionTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metric/MetricsCollectionTest.java @@ -30,6 +30,8 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; +import java.util.Objects; + public class MetricsCollectionTest { @RegisterExtension @Order(0) @@ -48,7 +50,7 @@ void canRecoverFDBLevelMetrics() { * Most of these metrics are created simply by defining the system and creating a database, so we don't have * to do too much */ - MetricSet ms = relational.getEngine().getEngineMetrics(); + MetricSet ms = Objects.requireNonNull(relational.getEngine()).getEngineMetrics(); Assertions.assertThat(ms.getMetrics()) .containsKey("jni calls") .containsKey("fetches") @@ -65,7 +67,7 @@ void canRecoverRecordLayerMetrics() { * Most of these metrics are created simply by defining the system and creating a database, so we don't have * to do too much */ - MetricSet ms = relational.getEngine().getEngineMetrics(); + MetricSet ms = Objects.requireNonNull(relational.getEngine()).getEngineMetrics(); Assertions.assertThat(ms.getMetrics()) .containsKey("wait for load record") .containsKey("create record store") diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metric/StoreTimerMetricCollectorFromMetricRegistryTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metric/StoreTimerMetricCollectorFromMetricRegistryTest.java index 616cbc421a5..d85e8b7e6d8 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metric/StoreTimerMetricCollectorFromMetricRegistryTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metric/StoreTimerMetricCollectorFromMetricRegistryTest.java @@ -59,8 +59,10 @@ void getCountsForCounterThrowsWhenAbsent() { @Test void getAverageTimeMicrosForEventReturnsAverageOfClockedSamples() throws Exception { final var collector = StoreTimerMetricCollector.fromMetricRegistry(new MetricRegistry()); - collector.clock(RelationalMetric.RelationalEvent.LEX_PARSE, () -> null); - collector.clock(RelationalMetric.RelationalEvent.LEX_PARSE, () -> null); + // The clocked value is discarded; a non-null placeholder avoids relying on clock()'s generic bound to permit a null Supplier result here. + collector.clock(RelationalMetric.RelationalEvent.LEX_PARSE, () -> new Object()); + collector.clock(RelationalMetric.RelationalEvent.LEX_PARSE, () -> new Object()); // Two samples were recorded; both ran to completion, so the average must be a finite non-negative number. final double averageMicros = collector.getAverageTimeMicrosForEvent(RelationalMetric.RelationalEvent.LEX_PARSE); Assertions.assertTrue(averageMicros >= 0.0, From cdee89997e66eee2dca244870dc75e79eff3a443 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Fri, 4 Sep 2026 12:09:45 -0400 Subject: [PATCH 24/42] WIP: fix NullAway errors in RecordLayerViewTests, IndexTest, SqlFunctionTest --- .../apple/foundationdb/relational/api/ddl/IndexTest.java | 6 ++++-- .../foundationdb/relational/api/ddl/SqlFunctionTest.java | 5 ++++- .../recordlayer/metadata/RecordLayerViewTests.java | 4 ++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/IndexTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/IndexTest.java index d07c36b13a6..e3a6088e41d 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/IndexTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/IndexTest.java @@ -53,6 +53,7 @@ import org.junit.jupiter.params.provider.ValueSource; import java.util.Locale; +import java.util.Objects; import java.util.function.Consumer; import static com.apple.foundationdb.record.RecordMetaDataProto.AndPredicate; @@ -99,8 +100,9 @@ void shouldFailWith(final String query, final ErrorCode errorCode, final String DdlTestUtil.getPlanGenerator(connection.getUnderlyingEmbeddedConnection(), database.getSchemaTemplateName(), "/IndexTest").getPlan(query)); Assertions.assertEquals(errorCode, ve.getErrorCode()); - Assertions.assertTrue(ve.getMessage().contains(errorMessage), String.format(Locale.ROOT, - "expected error message '%s' to contain '%s' but it didn't", ve.getMessage(), errorMessage)); + final String actualMessage = Objects.requireNonNullElse(ve.getMessage(), ve.toString()); + Assertions.assertTrue(actualMessage.contains(errorMessage), String.format(Locale.ROOT, + "expected error message '%s' to contain '%s' but it didn't", actualMessage, errorMessage)); connection.rollback(); connection.setAutoCommit(true); } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/SqlFunctionTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/SqlFunctionTest.java index 01c7026c670..554811b13d1 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/SqlFunctionTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/SqlFunctionTest.java @@ -42,6 +42,7 @@ import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -134,7 +135,9 @@ public ConstantAction getSaveSchemaTemplateConstantAction(final SchemaTemplate t }; } }); - return t.get(); + // The factory callback above always calls t.set(template) before shouldWorkWithInjectedFactory + // returns, so t is guaranteed non-null here. + return Objects.requireNonNull(t.get()); } @Test diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerViewTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerViewTests.java index 88527d19eb1..38322e7e7ca 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerViewTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerViewTests.java @@ -34,6 +34,10 @@ */ public class RecordLayerViewTests { + // The mock compiler is only ever stored/compared in these tests, never actually invoked to + // compile a view, so returning null here is safe even though Function + // doesn't declare a @Nullable return type. + @SuppressWarnings("NullAway") private static Function createMockCompiler() { return (Boolean parameter) -> null; } From 33fb1b8251857df1a662f7b3e64ada9ffb1d617e Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Fri, 4 Sep 2026 12:14:38 -0400 Subject: [PATCH 25/42] WIP: fix NullAway errors in CatalogValidatorTest, TemporaryFunctionTests --- .../relational/api/catalog/CatalogValidatorTest.java | 6 ++++++ .../recordlayer/query/TemporaryFunctionTests.java | 1 + 2 files changed, 7 insertions(+) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/catalog/CatalogValidatorTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/catalog/CatalogValidatorTest.java index eee5db7ff24..3054e932e66 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/catalog/CatalogValidatorTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/catalog/CatalogValidatorTest.java @@ -43,6 +43,9 @@ void testValidateGoodSchema() { void testValidateWithUnsetRecordLayerSchemaName() { RecordLayerSchema goodSchema = generateGoodSchema(); // clear schema_name field + // generateSchema's schemaName param is @Nonnull in the not-yet-migrated fdb-relational-api + // module, but this test intentionally passes null to exercise CatalogValidator's unset-field check. + @SuppressWarnings("NullAway") RecordLayerSchema schemaWithUnsetRecordLayerSchemaName = (RecordLayerSchema) goodSchema.getSchemaTemplate().generateSchema(goodSchema.getDatabaseName(), null); RelationalException exception = Assertions.assertThrows(RelationalException.class, () -> CatalogValidator.validateSchema(schemaWithUnsetRecordLayerSchemaName)); @@ -54,6 +57,9 @@ void testValidateWithUnsetRecordLayerSchemaName() { void testValidateWithUnsetDatabaseId() { RecordLayerSchema goodSchema = generateGoodSchema(); // clear database_id field + // generateSchema's databaseId param is @Nonnull in the not-yet-migrated fdb-relational-api + // module, but this test intentionally passes null to exercise CatalogValidator's unset-field check. + @SuppressWarnings("NullAway") RecordLayerSchema badRecordLayerSchema = (RecordLayerSchema) goodSchema.getSchemaTemplate().generateSchema(null, goodSchema.getName()); RelationalException exception = Assertions.assertThrows(RelationalException.class, () -> diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/TemporaryFunctionTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/TemporaryFunctionTests.java index 22977f36d08..0c7a81482be 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/TemporaryFunctionTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/TemporaryFunctionTests.java @@ -1130,6 +1130,7 @@ public ConstantAction getCreateTemporaryFunctionConstantAction(final SchemaTempl final var visitor = new BaseVisitor(new MutablePlanGenerationContext(PreparedParams.empty(), PlanHashable.PlanHashMode.VC0, statement, statement, 42), schemaTemplate, NoOpQueryFactory.INSTANCE, metadataOperationsFactory, URI.create("/FDB/FRL1"), false) { @Override + @SuppressWarnings("NullAway") // intentionally returns null; only the invocation is being tested here public LogicalOperator visitStatementBody(final RelationalParser.StatementBodyContext ctx) { called.set(true); return null; From 169be6ac1cea2907686a9994e8e71c0bb448d7a9 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Fri, 4 Sep 2026 12:17:09 -0400 Subject: [PATCH 26/42] WIP: fix import conflict in QueryLoggingTest (org.junit.Assert vs relational util.Assert) --- .../foundationdb/relational/recordlayer/QueryLoggingTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/QueryLoggingTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/QueryLoggingTest.java index 5640192cd22..ae721ce286e 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/QueryLoggingTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/QueryLoggingTest.java @@ -31,7 +31,6 @@ import com.apple.foundationdb.relational.recordlayer.query.AstNormalizer; import com.apple.foundationdb.relational.recordlayer.query.PlanContext; import com.apple.foundationdb.relational.recordlayer.query.PlanGenerator; -import com.apple.foundationdb.relational.util.Assert; import com.apple.foundationdb.relational.utils.SimpleDatabaseRule; import com.apple.foundationdb.relational.utils.TestSchemas; import org.apache.logging.log4j.Level; @@ -348,7 +347,7 @@ void testLogPlanHash() throws Exception { // invariant at runtime, but NullAway can't see that since Assert lives in the not-yet-migrated // fdb-relational-api module. @SuppressWarnings("NullAway") - final var metricCollector = Assert.notNullUnchecked(conn.getMetricCollector()); + final var metricCollector = com.apple.foundationdb.relational.util.Assert.notNullUnchecked(conn.getMetricCollector()); final var planContext = PlanContext.Builder.create() .fromRecordStore(store, conn.getOptions()) .fromDatabase(conn.getRecordLayerDatabase()) From 6a5527d77aa5379a40f2162835f3b65dd8047d19 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Fri, 4 Sep 2026 12:18:33 -0400 Subject: [PATCH 27/42] Fix NullAway errors in StatementBuilderTests, LogAppenderRule, EmbeddedRelationalExtension, ContinuationTest - StatementBuilderTests: use Objects.requireNonNull(whereClause) after the existing assertThat(whereClause).isNotNull() check (AssertJ's isNotNull() isn't understood by NullAway as narrowing). - LogAppenderRule/EmbeddedRelationalExtension: suppress NullAway.Init on constructors whose fields are set by beforeEach()/setup() (JUnit extension lifecycle, not the constructor); suppress the manual beforeEach(null)/ afterEach(null) invocations (JUnit's ExtensionContext parameter isn't annotated @Nullable, but these implementations ignore the context). - ContinuationTest: widen assertContinuation's underlying parameter to @Nullable Object (it's called with null in two tests); suppress the fromUnderlyingBytes(null) call site (its byte[] parameter is already @Nullable but NullAway doesn't reliably track array nullability). --- .../relational/recordlayer/ContinuationTest.java | 6 +++++- .../recordlayer/EmbeddedRelationalExtension.java | 9 +++++++++ .../relational/recordlayer/LogAppenderRule.java | 9 +++++++++ .../recordlayer/structuredsql/StatementBuilderTests.java | 7 ++++--- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/ContinuationTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/ContinuationTest.java index f1988c815e9..084bb04036d 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/ContinuationTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/ContinuationTest.java @@ -27,6 +27,7 @@ import com.google.protobuf.InvalidProtocolBufferException; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; +import org.jspecify.annotations.Nullable; import java.util.Properties; @@ -80,6 +81,9 @@ public void customProto() throws Exception { @Test public void testNullSameAsBegin() { + // fromUnderlyingBytes's bytes parameter is already @Nullable, but NullAway does not reliably track + // @Nullable on array-typed parameters. + @SuppressWarnings("NullAway") ContinuationImpl continuation = (ContinuationImpl) ContinuationImpl.fromUnderlyingBytes(null); assertContinuation(continuation, true, false, null); } @@ -89,7 +93,7 @@ public void invalidProtoFails() { Assertions.assertThatThrownBy(() -> ContinuationImpl.parseContinuation("Invalid".getBytes())).isInstanceOf(InvalidProtocolBufferException.class); } - private void assertContinuation(ContinuationImpl continuation, boolean atBeginning, boolean atEnd, Object underlying) { + private void assertContinuation(ContinuationImpl continuation, boolean atBeginning, boolean atEnd, @Nullable Object underlying) { Assertions.assertThat(continuation.atBeginning()).isEqualTo(atBeginning); Assertions.assertThat(continuation.atEnd()).isEqualTo(atEnd); Assertions.assertThat(continuation.getExecutionState()).isEqualTo(underlying); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalExtension.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalExtension.java index 4afe8bc1a1e..fa6b8bc4f4f 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalExtension.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalExtension.java @@ -73,6 +73,9 @@ public EmbeddedRelationalExtension(final Options options) { this(FDBTestEnvironment.randomClusterFile(), true, options); } + // storeCatalog and database are initialized by setup() (called from beforeEach()), which JUnit guarantees + // to run before any other method on this extension is used. + @SuppressWarnings("NullAway.Init") public EmbeddedRelationalExtension(final String clusterFile, final boolean register, final Options options) { final RelationalKeyspaceProvider keyspaceProvider = RelationalKeyspaceProvider.instance(); keyspaceProvider.registerDomainIfNotExists("TEST"); @@ -183,12 +186,18 @@ public static final class Resource implements Closeable { private final EmbeddedRelationalExtension underlyingExtension; + // BeforeEachCallback.beforeEach()'s ExtensionContext parameter isn't annotated @Nullable, but this + // implementation doesn't use the context, so invoking it manually with null is safe. + @SuppressWarnings("NullAway") Resource(final EmbeddedRelationalExtension underlyingExtension) throws Exception { this.underlyingExtension = underlyingExtension; this.underlyingExtension.beforeEach(null); } + // AfterEachCallback.afterEach()'s ExtensionContext parameter isn't annotated @Nullable, but this + // implementation doesn't use the context, so invoking it manually with null is safe. @Override + @SuppressWarnings("NullAway") public void close() { try { underlyingExtension.afterEach(null); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/LogAppenderRule.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/LogAppenderRule.java index 984e153ea5a..f1b2e602790 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/LogAppenderRule.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/LogAppenderRule.java @@ -61,12 +61,18 @@ public List getLogs() { } } + // logAppender, logger, and beforeLogLevel are initialized by beforeEach(), which JUnit guarantees to run + // (or which is invoked manually via of()) before any other method on this rule is used. + @SuppressWarnings("NullAway.Init") public LogAppenderRule(String name, Class clazz, Level level) { this.name = name; this.clazz = clazz; this.level = level; } + // BeforeEachCallback.beforeEach()'s ExtensionContext parameter isn't annotated @Nullable, but this + // implementation doesn't use the context, so invoking it manually with null is safe. + @SuppressWarnings("NullAway") public static LogAppenderRule of(String name, Class clazz, Level level) throws SQLException { final var rule = new LogAppenderRule(name, clazz, level); rule.beforeEach(null); @@ -94,7 +100,10 @@ public void beforeEach(ExtensionContext context) throws SQLException { logAppender.start(); } + // AfterEachCallback.afterEach()'s ExtensionContext parameter isn't annotated @Nullable, but this + // implementation doesn't use the context, so invoking it manually with null is safe. @Override + @SuppressWarnings("NullAway") public void close() throws SQLException { afterEach(null); } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/structuredsql/StatementBuilderTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/structuredsql/StatementBuilderTests.java index 7aeb6fb5efd..4bdacbe2e64 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/structuredsql/StatementBuilderTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/structuredsql/StatementBuilderTests.java @@ -37,6 +37,7 @@ import javax.annotation.Nonnull; import java.net.URI; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.stream.Stream; @@ -139,7 +140,7 @@ void examineWhereClause() throws Exception { var whereClause = updateBuilder.getWhereClause(); assertThat(whereClause) .isNotNull(); - assertThat(whereClause.toString()) + assertThat(Objects.requireNonNull(whereClause).toString()) .contains("{pk = 444}"); } } @@ -153,7 +154,7 @@ void examineMultipleWhereClauses() throws Exception { var whereClause = updateBuilder.getWhereClause(); assertThat(whereClause) .isNotNull(); - assertThat(whereClause.toString()) + assertThat(Objects.requireNonNull(whereClause).toString()) .contains("{pk = 444 AND ( a < 42 )}"); } } @@ -196,7 +197,7 @@ void addWhereClauses() throws Exception { assertThat(whereClause) .isNotNull(); // this is not very nice output, but I don't want to use the SQL visitor to check the string, i.e. I want the test to focus on one API call at a time if possible. - assertThat(whereClause.toString()) + assertThat(Objects.requireNonNull(whereClause).toString()) .contains("AND(({pk = 444 AND ( a < 42 )} : ???) : boolean ∪ ∅,LESS_THAN((B : long ∪ ∅) : long ∪ ∅,42 : long) : boolean ∪ ∅) : boolean ∪ ∅"); } } From 83cb8029df4fd5a54e10e41ee19ccd6818039e46 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Fri, 4 Sep 2026 12:21:16 -0400 Subject: [PATCH 28/42] Fix NullAway errors in DdlStatementParsingTest Replace dead "fail() then use null local" with "keys = fail(...)" (JUnit's fail() returns V, so no unreachable null assignment is needed); suppress the two Assert.notNullUnchecked(recordLayerIndex.getPredicate()) call sites (Assert lives in the not-yet-migrated fdb-relational-api module). --- .../relational/api/ddl/DdlStatementParsingTest.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/DdlStatementParsingTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/DdlStatementParsingTest.java index 7388cdb7227..47c64e9496d 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/DdlStatementParsingTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/DdlStatementParsingTest.java @@ -681,14 +681,14 @@ public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate templat Assertions.assertEquals("v_idx", index.getName(), "Incorrect index name!"); final var actualKe = ((RecordLayerIndex)index).getKeyExpression().toKeyExpression(); - List keys = null; + List keys; if (actualKe.hasThen()) { keys = new ArrayList<>(actualKe.getThen().getChildList()); } else if (actualKe.hasField()) { keys = new ArrayList<>(); keys.add(actualKe); } else { - Assertions.fail("Unexpected KeyExpression type"); + keys = Assertions.fail("Unexpected KeyExpression type"); } //if the first key is RecordType,remove that if (keys.get(0).hasRecordTypeKey()) { @@ -1403,6 +1403,9 @@ public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate templat assertThat(recordLayerIndex.getKeyExpression()).isEqualTo( Key.Expressions.concat(Key.Expressions.field("b"), Key.Expressions.field("c"))); assertThat(recordLayerIndex.getPredicate()).isNotNull(); + // Assert lives in the not-yet-migrated fdb-relational-api module and its parameters aren't + // annotated @Nullable, even though notNullUnchecked's entire purpose here is to null-check. + @SuppressWarnings("NullAway") final var predicate = Assert.notNullUnchecked(recordLayerIndex.getPredicate()); final var expectedPredicateProto = RecordMetaDataProto.Predicate.newBuilder() .setValuePredicate(RecordMetaDataProto.ValuePredicate.newBuilder().addValue("a") @@ -1446,6 +1449,9 @@ public ConstantAction getSaveSchemaTemplateConstantAction(SchemaTemplate templat assertThat(recordLayerIndex.getKeyExpression()).isEqualTo( Key.Expressions.concat(Key.Expressions.field("b"), Key.Expressions.field("c"))); assertThat(recordLayerIndex.getPredicate()).isNotNull(); + // Assert lives in the not-yet-migrated fdb-relational-api module and its parameters aren't + // annotated @Nullable, even though notNullUnchecked's entire purpose here is to null-check. + @SuppressWarnings("NullAway") final var predicate = Assert.notNullUnchecked(recordLayerIndex.getPredicate()); final var expectedPredicateProto = RecordMetaDataProto.Predicate.newBuilder() .setValuePredicate(RecordMetaDataProto.ValuePredicate.newBuilder().addValue("a") From 1b0685efbb598a65317be969d6821ff3ac3da609 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Fri, 4 Sep 2026 13:58:04 -0400 Subject: [PATCH 29/42] WIP: fix entries.get(0) suppression-doesn't-narrow bug in KeySpacePathParsingTest --- .../relational/recordlayer/KeySpacePathParsingTest.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/KeySpacePathParsingTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/KeySpacePathParsingTest.java index 850442893bf..c76476e1528 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/KeySpacePathParsingTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/KeySpacePathParsingTest.java @@ -53,6 +53,7 @@ import java.util.Base64; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.UUID; import java.util.function.Function; @@ -253,8 +254,7 @@ static Stream unsupportedType() { .map(type -> { // VALUES_FOR_TYPE covers every KeyType (verified by validateValuesForTypeCoverage()); // Map.get() is @Nullable per NullAway's built-in model, but the key is always present here. - @SuppressWarnings("NullAway") - final List entries = VALUES_FOR_TYPE.get(type); + final List entries = Objects.requireNonNull(VALUES_FOR_TYPE.get(type)); return Arguments.of(type, entries.get(0)); }); } @@ -278,8 +278,7 @@ static Stream supportedType() { .flatMap(type -> { // VALUES_FOR_TYPE covers every KeyType (verified by validateValuesForTypeCoverage()); // Map.get() is @Nullable per NullAway's built-in model, but the key is always present here. - @SuppressWarnings("NullAway") - final List entries = VALUES_FOR_TYPE.get(type); + final List entries = Objects.requireNonNull(VALUES_FOR_TYPE.get(type)); return ParameterizedTestUtils.booleans("constant") .flatMap(constant -> entries.stream() .map(pathEntry -> Arguments.of(type, constant, pathEntry))); From 338fc54800ee4ac4bd66766277bfd7fd7d2f8900 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Fri, 4 Sep 2026 13:58:56 -0400 Subject: [PATCH 30/42] WIP: fix resolved/resolvedParent suppression-doesn't-narrow bug in KeySpacePathParsingTest --- .../relational/recordlayer/KeySpacePathParsingTest.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/KeySpacePathParsingTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/KeySpacePathParsingTest.java index c76476e1528..490ad57ba24 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/KeySpacePathParsingTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/KeySpacePathParsingTest.java @@ -602,13 +602,11 @@ private List getResolvedValuesForKeySpacePath(KeySpacePath path, FDBReco KeySpacePath currentPath = path; // asyncToSync()'s generic return type isn't nullability-annotated in this unmigrated // record-layer-core API, but resolveAsync() never completes with a null PathValue. - @SuppressWarnings("NullAway") - PathValue resolved = context.asyncToSync(FDBStoreTimer.Waits.WAIT_KEYSPACE_PATH_RESOLVE, currentPath.resolveAsync(context)); + PathValue resolved = Objects.requireNonNull(context.asyncToSync(FDBStoreTimer.Waits.WAIT_KEYSPACE_PATH_RESOLVE, currentPath.resolveAsync(context))); values.add(resolved.getResolvedValue()); while (currentPath.getParent() != null) { currentPath = currentPath.getParent(); - @SuppressWarnings("NullAway") - PathValue resolvedParent = context.asyncToSync(FDBStoreTimer.Waits.WAIT_KEYSPACE_PATH_RESOLVE, currentPath.resolveAsync(context)); + PathValue resolvedParent = Objects.requireNonNull(context.asyncToSync(FDBStoreTimer.Waits.WAIT_KEYSPACE_PATH_RESOLVE, currentPath.resolveAsync(context))); values.add(resolvedParent.getResolvedValue()); } return values; From f9e6908d1597ade698806f06355101c169b18239 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Fri, 4 Sep 2026 14:16:41 -0400 Subject: [PATCH 31/42] Fix PMD/Checkstyle/SpotBugs findings surfaced after NullAway wiring - ProceduralPlan.java: remove now-unused jspecify Nullable import (PMD UnnecessaryImport / Checkstyle UnusedImportsCheck). - ExpressionVisitor.java: drop a dead "= null" initializer whose value is always overwritten before use in every branch (PMD UnusedAssignment). - WindowSpecExpression.java / WithPlanGenerationSideEffects.java / CaseInsensitiveCharStream.java / NoOpMetricCollector.java: restore the blank line between the last import and the following class/interface Javadoc, lost during the mechanical jspecify-import swap (Checkstyle EmptyLineSeparatorCheck). - RecordMetadataSerializer.java / QueryPlan.java: SpotBugs NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE -- both called a @Nullable getter (getPredicate()/getCompiledStatement()) twice in a null-check ternary and used the second, unchecked call in the non-null branch; hoist to a single local variable instead. --- .../recordlayer/metadata/serde/RecordMetadataSerializer.java | 3 ++- .../recordlayer/query/CaseInsensitiveCharStream.java | 1 + .../relational/recordlayer/query/ProceduralPlan.java | 1 - .../foundationdb/relational/recordlayer/query/QueryPlan.java | 3 ++- .../relational/recordlayer/query/WindowSpecExpression.java | 1 + .../query/functions/WithPlanGenerationSideEffects.java | 1 + .../recordlayer/query/visitors/ExpressionVisitor.java | 2 +- .../recordlayer/query/cache/NoOpMetricCollector.java | 1 + 8 files changed, 9 insertions(+), 4 deletions(-) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/RecordMetadataSerializer.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/RecordMetadataSerializer.java index 5cd552135d2..e1d7567240a 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/RecordMetadataSerializer.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/serde/RecordMetadataSerializer.java @@ -81,12 +81,13 @@ public void visit(com.apple.foundationdb.relational.api.metadata.Index index) { // See: TODO (Relational index misses version information) Assert.thatUnchecked(index instanceof RecordLayerIndex); final RecordLayerIndex recLayerIndex = (RecordLayerIndex) index; + final var predicate = recLayerIndex.getPredicate(); getBuilder().addIndex(recLayerIndex.getTableStorageName(), new Index(index.getName(), recLayerIndex.getKeyExpression(), index.getIndexType(), recLayerIndex.getOptions(), - recLayerIndex.getPredicate() == null ? null : IndexPredicate.fromProto(recLayerIndex.getPredicate()))); + predicate == null ? null : IndexPredicate.fromProto(predicate))); } @Override diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CaseInsensitiveCharStream.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CaseInsensitiveCharStream.java index cf7b26d7bf5..1c09efc4e4e 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CaseInsensitiveCharStream.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CaseInsensitiveCharStream.java @@ -26,6 +26,7 @@ import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.IntStream; import org.antlr.v4.runtime.misc.Interval; + /** * A {@link IntStream} stream, that enables allows a case-sensitive {@link org.antlr.v4.runtime.Lexer} * to become case-insensitive by upper-casing the stream of symbols arriving to it. diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ProceduralPlan.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ProceduralPlan.java index 40425be0949..90d18216702 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ProceduralPlan.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ProceduralPlan.java @@ -29,7 +29,6 @@ import com.apple.foundationdb.relational.api.exceptions.RelationalException; import com.apple.foundationdb.relational.api.metrics.RelationalMetric; -import org.jspecify.annotations.Nullable; import java.util.Objects; @API(API.Status.EXPERIMENTAL) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryPlan.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryPlan.java index ab60518f546..ca06ab3f0bf 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryPlan.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryPlan.java @@ -342,7 +342,8 @@ private RelationalResultSet executeExplain(ContinuationImpl parsedContinuation, // ArrayRow's vararg parameter type isn't @Nullable (NullAway/JSpecify doesn't reliably track // element nullability for array/vararg-typed parameters); PLAN_SERIALIZATION_MODE and the plan // complexity below are genuinely null in some cases. - final Object planSerializationMode = parsedContinuation.getCompiledStatement() == null ? null : parsedContinuation.getCompiledStatement().getPlanSerializationMode(); + final var compiledStatement = parsedContinuation.getCompiledStatement(); + final Object planSerializationMode = compiledStatement == null ? null : compiledStatement.getPlanSerializationMode(); @SuppressWarnings("NullAway") final ArrayRow continuationRow = new ArrayRow( parsedContinuation.getExecutionState(), diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/WindowSpecExpression.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/WindowSpecExpression.java index 8371e121c92..6ff290e33de 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/WindowSpecExpression.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/WindowSpecExpression.java @@ -24,6 +24,7 @@ import com.apple.foundationdb.record.query.plan.cascades.WindowOrderingPart; import com.google.common.collect.ImmutableList; import com.google.common.collect.Streams; + /** * Helper class that captures the components of an SQL {@code OVER} clause used in window functions. *

diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/WithPlanGenerationSideEffects.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/WithPlanGenerationSideEffects.java index 3e385c1cad8..725946fbbe8 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/WithPlanGenerationSideEffects.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/WithPlanGenerationSideEffects.java @@ -21,6 +21,7 @@ package com.apple.foundationdb.relational.recordlayer.query.functions; import com.apple.foundationdb.relational.recordlayer.query.Literals; + /** * Trait used to capture side effects resulting from the integration of a * {@link com.apple.foundationdb.record.query.plan.cascades.UserDefinedFunction} into a query plan. diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/ExpressionVisitor.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/ExpressionVisitor.java index fa66d32ce9f..7d3419eaa87 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/ExpressionVisitor.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/ExpressionVisitor.java @@ -1069,7 +1069,7 @@ private Expressions parseRecordFieldsUnderReorderings(final List= 0 && index < providedColumnContexts.size()) { currentFieldColumns = parseRecordField(providedColumnContexts.get(index), elementField); } else if (index >= providedColumnContexts.size()) { diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/NoOpMetricCollector.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/NoOpMetricCollector.java index fff26d78e4b..d686de7ad0f 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/NoOpMetricCollector.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/cache/NoOpMetricCollector.java @@ -24,6 +24,7 @@ import com.apple.foundationdb.relational.api.metrics.MetricCollector; import com.apple.foundationdb.relational.api.metrics.RelationalMetric; import com.apple.foundationdb.relational.util.Supplier; + /** * A no-op {@link MetricCollector} for use in tests that do not need to track metrics. */ From decfbc6879b36c24f64dc88700b2ea5a67a7be30 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Fri, 4 Sep 2026 14:21:04 -0400 Subject: [PATCH 32/42] Fix regressed byte[] array-nullability mismatch in PlanGenerator.java setContinuation(continuationProto) -- both sides already correctly declared @Nullable byte[] -- still tripped NullAway's known array-type matching limitation. Extracted into a small suppressed private helper (setContinuationOnContext) instead of a broad method-level suppression, since the call is a bare void-method statement that can't otherwise carry a @SuppressWarnings. --- .../relational/recordlayer/query/PlanGenerator.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanGenerator.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanGenerator.java index c62e4feb1bf..b68922c315c 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanGenerator.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/PlanGenerator.java @@ -305,6 +305,15 @@ private static CopyPlan generatePhysicalPlanForCopyContinuation( return copyPlan; } + // MutablePlanGenerationContext#setContinuation(...) already correctly declares its parameter + // @Nullable byte[], matching continuationProto's own type here, but NullAway/JSpecify does not + // reliably match up @Nullable byte[]-to-@Nullable byte[] array-typed parameters (known limitation). + @SuppressWarnings("NullAway") + private static void setContinuationOnContext(final MutablePlanGenerationContext planGenerationContext, + @Nullable final byte[] continuationProto) { + planGenerationContext.setContinuation(continuationProto); + } + private static QueryPlan.ContinuedPhysicalQueryPlan generatePhysicalPlanForCompiledStatementContinuation( final AstNormalizer.NormalizationResult ast, final Set validPlanHashModes, @@ -371,7 +380,7 @@ private static QueryPlan.ContinuedPhysicalQueryPlan generatePhysicalPlanForCompi ast.getQueryCacheKey().getCanonicalQueryString(), Objects.requireNonNull(continuation.getBindingHash())); planGenerationContext.setForExplain(ast.getQueryExecutionContext().isForExplain()); Arrays.stream(orderedLiterals).forEach(literal -> planGenerationContext.getLiteralsBuilder().addLiteral(literal)); - planGenerationContext.setContinuation(continuationProto); + setContinuationOnContext(planGenerationContext, continuationProto); final var continuationPlanConstraint = QueryPlanConstraint.fromProto(serializationContext, compiledStatement.getPlanConstraint()); From f733c3272a0facabbff40c4dcb348c0686873cca Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Fri, 4 Sep 2026 14:26:15 -0400 Subject: [PATCH 33/42] Work around PMD 6.44.0 qualified-nested-type parser bug in RecordLayerIterator PMD 6.44.0 cannot parse 'RecordCursor.@Nullable NoNextReason' (a type-use annotation on a qualified nested type) and throws a ParseException for the whole file instead of just skipping the annotation. Unlike RecordLayerIndex.Builder (which collides with ImmutableMap.Builder's simple name and must keep the qualified form), NoNextReason has no simple-name collision here, so import it directly and use the simple name everywhere in the file (including the now-plain '@Nullable NoNextReason' field and every other RecordCursor.NoNextReason reference), matching the documented workaround. --- .../recordlayer/RecordLayerIterator.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerIterator.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerIterator.java index 31df59af356..5be756ff061 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerIterator.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordLayerIterator.java @@ -24,6 +24,7 @@ import com.apple.foundationdb.record.RecordCoreException; import com.apple.foundationdb.record.RecordCursor; +import com.apple.foundationdb.record.RecordCursor.NoNextReason; import com.apple.foundationdb.record.RecordCursorResult; import com.apple.foundationdb.relational.api.Continuation; import com.apple.foundationdb.relational.api.Row; @@ -46,7 +47,8 @@ public final class RecordLayerIterator implements ResumableIterator { private RecordCursorResult result; private Continuation continuation; // null until iteration is exhausted; see fetchNextResult() and getNoNextReason() below. - private RecordCursor.@Nullable NoNextReason noNextReason; + @Nullable + private NoNextReason noNextReason; private RecordLayerIterator(RecordCursor cursor, Function transform) throws RelationalException { this.recordCursor = cursor; @@ -97,9 +99,9 @@ private RecordCursorResult fetchNextResult() { currentResult = recordCursor.getNext(); result = currentResult; if (!currentResult.hasNext()) { - final RecordCursor.NoNextReason reason = currentResult.getNoNextReason(); + final NoNextReason reason = currentResult.getNoNextReason(); noNextReason = reason; - if (reason == RecordCursor.NoNextReason.SOURCE_EXHAUSTED) { + if (reason == NoNextReason.SOURCE_EXHAUSTED) { this.continuation = ContinuationImpl.END; } else { // NullAway/JSpecify does not reliably track @Nullable on array-typed (byte[]) parameters: @@ -147,12 +149,12 @@ public Row next() { public boolean terminatedEarly() { return !hasNext() && noNextReason != null && - noNextReason != RecordCursor.NoNextReason.SOURCE_EXHAUSTED && - noNextReason != RecordCursor.NoNextReason.RETURN_LIMIT_REACHED; + noNextReason != NoNextReason.SOURCE_EXHAUSTED && + noNextReason != NoNextReason.RETURN_LIMIT_REACHED; } @Override - public RecordCursor.NoNextReason getNoNextReason() { + public NoNextReason getNoNextReason() { // Only meaningful (and only ever called) once iteration has ended, at which point fetchNextResult() // has already set noNextReason; see terminatedEarly() and RecordLayerResultSet's caller. return Objects.requireNonNull(noNextReason, "getNoNextReason() called before iteration ended"); From 6cddfa89cb195f646d32cece6ef426241b2ded59 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Fri, 4 Sep 2026 14:29:51 -0400 Subject: [PATCH 34/42] Remove temporary -Xmaxerrs diagnostic override from fdb-relational-core.gradle --- fdb-relational-core/fdb-relational-core.gradle | 2 -- 1 file changed, 2 deletions(-) diff --git a/fdb-relational-core/fdb-relational-core.gradle b/fdb-relational-core/fdb-relational-core.gradle index 8d15c25b727..68db55629d5 100644 --- a/fdb-relational-core/fdb-relational-core.gradle +++ b/fdb-relational-core/fdb-relational-core.gradle @@ -96,8 +96,6 @@ tasks.withType(JavaCompile).configureEach { option("NullAway:JSpecifyMode", "true") option("NullAway:AcknowledgeRestrictiveAnnotations", "true") } - // TEMP-DIAGNOSTIC: remove before finishing -- see full error list instead of javac's default 100-cap. - options.compilerArgs << "-Xmaxerrs" << "10000" } publishing { From 373f0b51f630dc2f205f05191da09ed090de2a8c Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Sun, 6 Sep 2026 15:47:40 +0100 Subject: [PATCH 35/42] Remove redundant @Nonnull left over from a merge (non-null is the @NullMarked default) --- .../relational/recordlayer/EmbeddedRelationalConnection.java | 1 - 1 file changed, 1 deletion(-) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalConnection.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalConnection.java index 1adf780948d..9a7d29a1e75 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalConnection.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalConnection.java @@ -428,7 +428,6 @@ public void setOption(Options.Name name, Object value) throws SQLException { } @Override - @Nonnull public URI getPath() { return getRecordLayerDatabase().getURI(); } From 966fc364aa4b96ebfd605ff96bdd6c05b486eed1 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Sun, 6 Sep 2026 17:46:00 +0100 Subject: [PATCH 36/42] Fix 22 NullAway errors in fdb-relational-core main sources fdb-relational-api's finalized contracts (RelationalStruct/RelationalArray/ RelationalResultSet methods that legitimately return @Nullable, and RelationalDriver#connect()) are now visible to fdb-relational-core's NullAway pass. - ErrorCapturingResultSet: widen getArray/getUUID/getStruct to @Nullable to match the real delegate contract in RelationalStruct. - RecordTypeTable#toDynamicMessage: fix a real latent NPE risk, a NULL array-valued column reaching the non-repeated/wrapped ARRAY branch would previously dereference a null array; now skipped consistently with the other nullable-field cases. - RelationalKeyspaceProvider#getSchemaName: use Objects.requireNonNull with a message, KeySpacePath#getValue() is @Nullable in general but is guaranteed non-null once the directory name is confirmed to be SCHEMA_DIR. - QueryPlan, QueryExecutor, RecordLayerStoreSchemaTemplateCatalog, RecordLayerStoreCatalog, BackingRecordStore, BackingLocatableResolverStore, CopyPlan: suppress with explanation, byte[] continuation values are genuinely @Nullable on both sides of these calls, but NullAway/JSpecify does not reliably track @Nullable across array-typed parameters (known tooling limitation). --- .../recordlayer/ErrorCapturingResultSet.java | 8 ++++ .../relational/recordlayer/QueryExecutor.java | 11 +++++- .../recordlayer/RecordTypeTable.java | 2 +- .../RelationalKeyspaceProvider.java | 6 ++- .../catalog/RecordLayerStoreCatalog.java | 8 +++- ...RecordLayerStoreSchemaTemplateCatalog.java | 32 +++++++++++++-- .../recordlayer/query/CopyPlan.java | 7 +++- .../recordlayer/query/QueryPlan.java | 7 +++- .../BackingLocatableResolverStore.java | 18 ++++++++- .../storage/BackingRecordStore.java | 39 +++++++++++++++++-- 10 files changed, 122 insertions(+), 16 deletions(-) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ErrorCapturingResultSet.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ErrorCapturingResultSet.java index 28346116652..25b8bdac00a 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ErrorCapturingResultSet.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ErrorCapturingResultSet.java @@ -28,6 +28,8 @@ import com.apple.foundationdb.relational.api.RelationalStruct; import com.apple.foundationdb.relational.recordlayer.util.ExceptionUtil; +import org.jspecify.annotations.Nullable; + import java.sql.SQLException; import java.util.UUID; @@ -216,6 +218,7 @@ public Object getObject(String columnLabel) throws SQLException { } @Override + @Nullable public RelationalArray getArray(int columnIndex) throws SQLException { try { return delegate.getArray(columnIndex); @@ -225,6 +228,7 @@ public RelationalArray getArray(int columnIndex) throws SQLException { } @Override + @Nullable public RelationalArray getArray(String columnLabel) throws SQLException { try { return delegate.getArray(columnLabel); @@ -234,6 +238,7 @@ public RelationalArray getArray(String columnLabel) throws SQLException { } @Override + @Nullable public UUID getUUID(final int oneBasedPosition) throws SQLException { try { return delegate.getUUID(oneBasedPosition); @@ -243,6 +248,7 @@ public UUID getUUID(final int oneBasedPosition) throws SQLException { } @Override + @Nullable public UUID getUUID(final String fieldName) throws SQLException { try { return delegate.getUUID(fieldName); @@ -266,6 +272,7 @@ public Continuation getContinuation() throws SQLException { } @Override + @Nullable public RelationalStruct getStruct(String columnLabel) throws SQLException { try { return delegate.getStruct(columnLabel); @@ -275,6 +282,7 @@ public RelationalStruct getStruct(String columnLabel) throws SQLException { } @Override + @Nullable public RelationalStruct getStruct(int oneBasedColumn) throws SQLException { try { return delegate.getStruct(oneBasedColumn); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/QueryExecutor.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/QueryExecutor.java index a6c8a0c0628..7174fcae1fb 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/QueryExecutor.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/QueryExecutor.java @@ -57,9 +57,18 @@ public QueryExecutor(final RecordQueryPlan plan, public ResumableIterator execute(@Nullable final Continuation continuation, final ExecuteProperties executeProperties) throws RelationalException { final FDBRecordStoreBase fdbRecordStore = Assert.notNull(schema.loadStore()).unwrap(FDBRecordStoreBase.class); + // continuation.getExecutionState() is @Nullable byte[]; NullAway/JSpecify does not reliably track + // @Nullable on array types across the call into executePlan's continuation parameter (also + // @Nullable byte[]), so this ternary is flagged as mismatched even though both sides agree it can be null. + @SuppressWarnings("NullAway") + final byte[] executionState = continuation == null ? null : continuation.getExecutionState(); + // See the comment above: executionState is genuinely @Nullable byte[], and executePlan's + // continuation parameter is likewise @Nullable byte[]; the mismatch NullAway reports here is the + // same array-tracking gap. + @SuppressWarnings("NullAway") final RecordCursor cursor = plan.executePlan(fdbRecordStore, evaluationContext, - continuation == null ? null : continuation.getExecutionState(), executeProperties); + executionState, executeProperties); return RecordLayerIterator.create(cursor, messageFDBQueriedRecord -> new MessageTuple(messageFDBQueriedRecord.getMessage())); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordTypeTable.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordTypeTable.java index 65260dad844..b416936305a 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordTypeTable.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RecordTypeTable.java @@ -258,7 +258,7 @@ public static Message toDynamicMessage(RelationalStruct struct, Descriptors.Desc builder.addRepeatedField(fd, arrayItem); } } - } else { + } else if (array != null) { Assert.that(fd.getType() == Descriptors.FieldDescriptor.Type.MESSAGE, ErrorCode.CANNOT_CONVERT_TYPE, "Field Type expected to be of Type ARRAY but is actually " + fd.getType()); Assert.that(NullableArrayUtils.isWrappedArrayDescriptor(fd.getMessageType())); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RelationalKeyspaceProvider.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RelationalKeyspaceProvider.java index 188d0bc7cab..9a19f64cbeb 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RelationalKeyspaceProvider.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/RelationalKeyspaceProvider.java @@ -37,6 +37,7 @@ import com.google.common.annotations.VisibleForTesting; import java.net.URI; +import java.util.Objects; import java.util.concurrent.CompletableFuture; /** @@ -162,7 +163,10 @@ public RelationalSchemaPath(KeySpacePath inner) { public String getSchemaName() { String directoryName = getDirectoryName(); if (SCHEMA_DIR.equals(directoryName)) { - return (String) getValue(); + // A path whose directory is SCHEMA_DIR was constructed via add(SCHEMA_DIR, schemaName) with a + // non-null String schemaName (see RelationalDatabasePath#schemaPath above), so getValue() is + // guaranteed non-null here even though its general contract is @Nullable. + return (String) Objects.requireNonNull(getValue(), "schema path value must not be null for the \"" + SCHEMA_DIR + "\" directory"); } else { return directoryName; } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalog.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalog.java index 2b94ea7f39f..f9dae25e926 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalog.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreCatalog.java @@ -410,9 +410,15 @@ public KeySpace getKeySpace() { // throws exception otherwise. private boolean deleteSchemas(FDBRecordStoreBase recordStore, URI dbUri) throws RelationalException { Tuple key = Tuple.from(SystemTableRegistry.SCHEMA_RECORD_TYPE_KEY, dbUri.getPath()); + // ContinuationImpl.BEGIN.getExecutionState() is @Nullable byte[]; NullAway/JSpecify does not + // reliably track @Nullable on array types across the call into scanRecords's continuation + // parameter (also @Nullable byte[]), so this is flagged as mismatched even though both sides + // agree it can be null. + @SuppressWarnings("NullAway") + final byte[] beginExecutionState = ContinuationImpl.BEGIN.getExecutionState(); try (RecordCursor> cursor = recordStore.scanRecords(new TupleRange(key, key, EndpointType.RANGE_INCLUSIVE, - EndpointType.RANGE_INCLUSIVE), ContinuationImpl.BEGIN.getExecutionState(), + EndpointType.RANGE_INCLUSIVE), beginExecutionState, ScanProperties.FORWARD_SCAN);) { RecordCursorResult> cursorResult; do { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreSchemaTemplateCatalog.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreSchemaTemplateCatalog.java index dbd23a8f023..beccb288bcc 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreSchemaTemplateCatalog.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/RecordLayerStoreSchemaTemplateCatalog.java @@ -112,10 +112,16 @@ public boolean doesSchemaTemplateExist(Transaction txn, String schemaTemplateNam var recordStore = RecordLayerStoreUtils.openRecordStore(txn, this.catalogSchemaPath, this.catalogRecordMetaDataProvider); try { + // ContinuationImpl.BEGIN.getExecutionState() is @Nullable byte[]; NullAway/JSpecify does not + // reliably track @Nullable on array types across the call into scanRecords's continuation + // parameter (also @Nullable byte[]), so this is flagged as mismatched even though both sides + // agree it can be null. + @SuppressWarnings("NullAway") + final byte[] beginExecutionState = ContinuationImpl.BEGIN.getExecutionState(); try (RecordCursor> cursor = recordStore.scanRecords(new TupleRange(key, key, EndpointType.RANGE_INCLUSIVE, EndpointType.RANGE_INCLUSIVE), - ContinuationImpl.BEGIN.getExecutionState(), ScanProperties.REVERSE_SCAN)) { + beginExecutionState, ScanProperties.REVERSE_SCAN)) { RecordCursorResult> cursorResult = cursor.getNext(); return cursorResult != null && !cursorResult.getContinuation().isEnd() && cursorResult.get() != null; } @@ -173,7 +179,13 @@ public SchemaTemplate loadSchemaTemplate(final Transaction txn, final String tem final var key = getSchemaTemplatePrimaryKey(templateName); final var recordStore = RecordLayerStoreUtils.openRecordStore(txn, catalogSchemaPath, catalogRecordMetaDataProvider); final var tupleRange = new TupleRange(key, key, EndpointType.RANGE_INCLUSIVE, EndpointType.RANGE_INCLUSIVE); - try (var cursor = recordStore.scanRecords(tupleRange, ContinuationImpl.BEGIN.getExecutionState(), ScanProperties.REVERSE_SCAN)) { + // ContinuationImpl.BEGIN.getExecutionState() is @Nullable byte[]; NullAway/JSpecify does not + // reliably track @Nullable on array types across the call into scanRecords's continuation + // parameter (also @Nullable byte[]), so this is flagged as mismatched even though both sides + // agree it can be null. + @SuppressWarnings("NullAway") + final byte[] beginExecutionState = ContinuationImpl.BEGIN.getExecutionState(); + try (var cursor = recordStore.scanRecords(tupleRange, beginExecutionState, ScanProperties.REVERSE_SCAN)) { final var cursorResult = cursor.getNext(); final var schemaExists = !cursorResult.getContinuation().isEnd() && cursorResult.get() != null; Assert.thatUnchecked(schemaExists, ErrorCode.UNKNOWN_SCHEMA_TEMPLATE, @@ -250,10 +262,16 @@ public RelationalResultSet listTemplates(Transaction txn) { try { var recordStore = RecordLayerStoreUtils.openRecordStore(txn, this.catalogSchemaPath, this.catalogRecordMetaDataProvider); + // ContinuationImpl.BEGIN.getExecutionState() is @Nullable byte[]; NullAway/JSpecify does not + // reliably track @Nullable on array types across the call into scanRecords's continuation + // parameter (also @Nullable byte[]), so this is flagged as mismatched even though both sides + // agree it can be null. + @SuppressWarnings("NullAway") + final byte[] beginExecutionState = ContinuationImpl.BEGIN.getExecutionState(); RecordCursor> cursor = recordStore.scanRecords(new TupleRange(key, key, EndpointType.RANGE_INCLUSIVE, EndpointType.RANGE_INCLUSIVE), - ContinuationImpl.BEGIN.getExecutionState(), ScanProperties.FORWARD_SCAN); + beginExecutionState, ScanProperties.FORWARD_SCAN); Descriptors.Descriptor d = recordStore.getRecordMetaData().getRecordMetaData() .getRecordType(SchemaTemplateSystemTable.TABLE_NAME).getDescriptor(); final var structMetaData = RelationalStructMetaData.of((DataType.StructType) DataTypeUtils.toRelationalType(ProtobufDdlUtil.recordFromDescriptor(d))); @@ -290,10 +308,16 @@ public void deleteTemplate(Transaction txn, String templateName, boolean throwIf try { var recordStore = RecordLayerStoreUtils.openRecordStore(txn, this.catalogSchemaPath, this.catalogRecordMetaDataProvider); + // ContinuationImpl.BEGIN.getExecutionState() is @Nullable byte[]; NullAway/JSpecify does not + // reliably track @Nullable on array types across the call into scanRecords's continuation + // parameter (also @Nullable byte[]), so this is flagged as mismatched even though both sides + // agree it can be null. + @SuppressWarnings("NullAway") + final byte[] beginExecutionState = ContinuationImpl.BEGIN.getExecutionState(); try (RecordCursor> cursor = recordStore.scanRecords(new TupleRange(key, key, EndpointType.RANGE_INCLUSIVE, EndpointType.RANGE_INCLUSIVE), - ContinuationImpl.BEGIN.getExecutionState(), ScanProperties.FORWARD_SCAN);) { + beginExecutionState, ScanProperties.FORWARD_SCAN);) { RecordCursorResult> cursorResult; boolean deletedSomething = false; do { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java index 31509d71e05..7d6389fb4dd 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java @@ -225,8 +225,13 @@ private RelationalResultSet executeExport(ExecutionContext context) throws Relat scanProperties = scanProperties.with(executeProperties -> executeProperties.setReturnedRowLimit(limit)); } // Export all data from the path (up to the requested limit) + // continuation is already correctly declared @Nullable byte[] above; NullAway/JSpecify does not + // reliably track @Nullable on array-typed fields across this call into exportAllData's + // continuation parameter (also @Nullable byte[]), known limitation. + @SuppressWarnings("NullAway") + final byte[] exportContinuation = continuation; RecordCursor cursor = - keySpacePath.exportAllData(fdbContext, continuation, scanProperties); + keySpacePath.exportAllData(fdbContext, exportContinuation, scanProperties); // Track which paths we've already checked for schemas // Maps path -> SchemaTemplateInfo (or null if path has no schema) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryPlan.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryPlan.java index ca06ab3f0bf..72be42d83fd 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryPlan.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/QueryPlan.java @@ -434,9 +434,14 @@ private RelationalResultSet executePhysicalPlan(final RecordLayerSchema recordLa .setReturnedRowLimit(options.getOption(Options.Name.MAX_ROWS)) .setDryRun(options.getOption(Options.Name.DRY_RUN)) .build(); + // parsedContinuation.getExecutionState() is @Nullable byte[]; NullAway/JSpecify does not reliably + // track @Nullable on array types across the call into executePlan's continuation parameter (also + // @Nullable byte[]), so this is flagged as mismatched even though both sides agree it can be null. + @SuppressWarnings("NullAway") + final byte[] executionState = parsedContinuation.getExecutionState(); cursor = executionContext.metricCollector.clock( RelationalMetric.RelationalEvent.EXECUTE_RECORD_QUERY_PLAN, () -> recordQueryPlan.executePlan(fdbRecordStore, evaluationContext, - parsedContinuation.getExecutionState(), + executionState, executeProperties)); final var currentPlanHashMode = OptionsUtils.getCurrentPlanHashMode(options); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingLocatableResolverStore.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingLocatableResolverStore.java index 38cc7bf96cf..9ce3d7c8e5c 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingLocatableResolverStore.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingLocatableResolverStore.java @@ -219,13 +219,21 @@ public RecordCursor> scanType(RecordType type, TupleRan throw new InternalErrorException("unsupported range"); } + // continuation.getExecutionState() is @Nullable byte[]; NullAway/JSpecify does not reliably track + // @Nullable on array types across the calls below (fromFuture / locatableResolver.scan), so this + // ternary and its later uses are flagged as mismatched even though both sides agree it can be null. + @SuppressWarnings("NullAway") final byte[] continuationBytes = continuation == null ? null : continuation.getExecutionState(); final ScanProperties scanProperties = QueryPropertiesUtils.getScanProperties(options); if (type.getName().equals(LocatableResolverMetaDataProvider.RESOLVER_STATE_TYPE_NAME)) { // todo: this does not use the scanProperties to track runtime information like rows scanned // see: https://github.com/FoundationDB/fdb-record-layer/issues/3226 final ExecuteProperties executeProperties = scanProperties.getExecuteProperties(); - return RecordCursor.fromFuture(context.getExecutor(), + // See the comment above: continuationBytes is genuinely @Nullable byte[], and fromFuture's + // continuation parameter is likewise @Nullable byte[]; the mismatch NullAway reports here is + // the same array-tracking gap. + @SuppressWarnings("NullAway") + final RecordCursor> result = RecordCursor.fromFuture(context.getExecutor(), () -> locatableResolver.loadResolverState(context).thenApply(state -> { Message msg = metaDataProvider.wrapResolverState(state); return FDBStoredRecord.newBuilder(msg) @@ -235,8 +243,13 @@ public RecordCursor> scanType(RecordType type, TupleRan }), continuationBytes ).skipThenLimit(executeProperties.getSkip(), executeProperties.getReturnedRowLimit()); + return result; } else if (type.getName().equals(LocatableResolverMetaDataProvider.INTERNING_TYPE_NAME)) { - return locatableResolver.scan(context, continuationBytes, scanProperties) + // See the comment above: continuationBytes is genuinely @Nullable byte[], and + // locatableResolver.scan's continuation parameter is likewise @Nullable byte[]; the mismatch + // NullAway reports here is the same array-tracking gap. + @SuppressWarnings("NullAway") + final RecordCursor> result = locatableResolver.scan(context, continuationBytes, scanProperties) .map(resolverKeyValue -> { // resolverKeyValue.getValue() is @Nonnull, so wrapResolverResult (which // only returns null when its result argument is null) always returns @@ -248,6 +261,7 @@ public RecordCursor> scanType(RecordType type, TupleRan .setPrimaryKey(Tuple.from(resolverKeyValue.getKey())) .build(); }); + return result; } else { throw new TypeNotPresentException(type.getName(), null); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingRecordStore.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingRecordStore.java index 5f221ee6580..88f0a68dc71 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingRecordStore.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/storage/BackingRecordStore.java @@ -108,7 +108,16 @@ public Row getFromIndex(Index index, Row key, Options options) throws Relational scanProperties = new ScanProperties(scanProperties.getExecuteProperties().setReturnedRowLimit(1), scanProperties.isReverse()); try { IndexEntry entry; - try (RecordCursorIterator indexEntryRecordCursor = recordStore.scanIndex(index, IndexScanType.BY_VALUE, TupleRange.allOf(TupleUtils.toFDBTuple(key)), null, scanProperties).asIterator()) { + // scanIndex's continuation parameter is @Nullable byte[]; NullAway/JSpecify does not reliably + // track @Nullable on array types for a literal null argument at this call site, so the null + // literal is flagged as mismatched even though the formal parameter genuinely accepts null (no + // continuation, i.e. start from the beginning of the index). + @SuppressWarnings("NullAway") + final byte[] noContinuation = null; + // See the comment above: noContinuation is genuinely null (by design), and scanIndex's + // continuation parameter is @Nullable byte[]; the mismatch NullAway reports here is the same + // array-tracking gap. + try (@SuppressWarnings("NullAway") RecordCursorIterator indexEntryRecordCursor = recordStore.scanIndex(index, IndexScanType.BY_VALUE, TupleRange.allOf(TupleUtils.toFDBTuple(key)), noContinuation, scanProperties).asIterator()) { if (!indexEntryRecordCursor.hasNext()) { return null; } @@ -191,8 +200,19 @@ public boolean insert(String tableName, Message message, boolean replaceOnDuplic public RecordCursor> scanType(RecordType type, TupleRange range, @Nullable Continuation continuation, Options options) throws RelationalException { try { final ScanProperties scanProps = QueryPropertiesUtils.getScanProperties(options); - return recordStore.scanRecords(range, continuation == null ? null : continuation.getExecutionState(), scanProps) + // continuation.getExecutionState() is @Nullable byte[]; NullAway/JSpecify does not reliably + // track @Nullable on array types across the call into scanRecords's continuation parameter + // (also @Nullable byte[]), so this ternary is flagged as mismatched even though both sides + // agree it can be null. + @SuppressWarnings("NullAway") + final byte[] executionState = continuation == null ? null : continuation.getExecutionState(); + // See the comment above: executionState is genuinely @Nullable byte[], and scanRecords's + // continuation parameter is likewise @Nullable byte[]; the mismatch NullAway reports here is + // the same array-tracking gap. + @SuppressWarnings("NullAway") + final RecordCursor> result = recordStore.scanRecords(range, executionState, scanProps) .filter(record -> type.equals(record.getRecordType())); + return result; } catch (RecordCoreException ex) { throw ExceptionUtil.toRelationalException(ex); } @@ -203,8 +223,19 @@ public RecordCursor scanIndex(Index index, TupleRange range, @Nullab //TODO(bfines) get scan type from Options and/or ScanProperties assert continuation == null || continuation instanceof ContinuationImpl; try { - return recordStore.scanIndex(index, IndexScanType.BY_VALUE, range, - continuation == null ? null : continuation.getExecutionState(), QueryPropertiesUtils.getScanProperties(options)); + // continuation.getExecutionState() is @Nullable byte[]; NullAway/JSpecify does not reliably + // track @Nullable on array types across the call into scanIndex's continuation parameter + // (also @Nullable byte[]), so this ternary is flagged as mismatched even though both sides + // agree it can be null. + @SuppressWarnings("NullAway") + final byte[] executionState = continuation == null ? null : continuation.getExecutionState(); + // See the comment above: executionState is genuinely @Nullable byte[], and scanIndex's + // continuation parameter is likewise @Nullable byte[]; the mismatch NullAway reports here is + // the same array-tracking gap. + @SuppressWarnings("NullAway") + final RecordCursor result = recordStore.scanIndex(index, IndexScanType.BY_VALUE, range, + executionState, QueryPropertiesUtils.getScanProperties(options)); + return result; } catch (RecordCoreException ex) { throw ExceptionUtil.toRelationalException(ex); } From 664715ecc2397aa14b7a71344beab8e22d8b62c9 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Sun, 6 Sep 2026 18:27:34 +0100 Subject: [PATCH 37/42] Fix 23 more NullAway test-source errors in fdb-relational-core (connect() nullability) RelationalDriver#connect() legitimately returns @Nullable RelationalConnection (a driver may decline a URL it doesn't handle), matching java.sql.Driver's contract. Test code assumed a non-null result and dereferenced it immediately; wrap with Objects.requireNonNull() (a null connection here is a real test setup failure that should fail fast with a clear message) in: EmbeddedRelationalExtension, QueryPropertiesTest, OptionScopeTest, QueryLoggingTest, CursorTest, ExecutePropertyTests, UpdateTest. Also: - RelationalConnectionRule: same fix for its connection field assignment, plus widen getPath() to @Nullable to match RelationalConnection#getPath()'s real contract. - EmbeddedRelationalExtension: widen clusterFile field/constructor/makeDatabase param to @Nullable, matching FDBTestEnvironment#randomClusterFile() and FDBDatabaseFactory#getDatabase(String)'s real contracts (null means "use the default cluster file"). - DdlRecordLayerSchemaTemplateTest: Objects.requireNonNull around a genuinely-nullable RelationalArray column value before dereferencing it. --- .../relational/recordlayer/CursorTest.java | 2 +- .../recordlayer/EmbeddedRelationalExtension.java | 7 +++++-- .../relational/recordlayer/OptionScopeTest.java | 5 +++-- .../relational/recordlayer/QueryLoggingTest.java | 16 ++++++++-------- .../recordlayer/QueryPropertiesTest.java | 3 ++- .../recordlayer/RelationalConnectionRule.java | 8 +++++++- .../ddl/DdlRecordLayerSchemaTemplateTest.java | 3 ++- .../recordlayer/query/ExecutePropertyTests.java | 13 +++++++------ .../relational/recordlayer/query/UpdateTest.java | 3 ++- 9 files changed, 37 insertions(+), 23 deletions(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CursorTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CursorTest.java index 3210e5f958f..08fd5cc5e11 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CursorTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/CursorTest.java @@ -203,7 +203,7 @@ public void continuationWithScanRowLimit() throws SQLException, RelationalExcept int numRowsReturned = 0; // 1. Iterate over and count the rows returned before the scan rows limit is hit final var driver = (RelationalDriver) DriverManager.getDriver(database.getConnectionUri().toString()); - try (final var conn = driver.connect(database.getConnectionUri(), Options.builder().withOption(Options.Name.EXECUTION_SCANNED_ROWS_LIMIT, 3).build())) { + try (final var conn = Objects.requireNonNull(driver.connect(database.getConnectionUri(), Options.builder().withOption(Options.Name.EXECUTION_SCANNED_ROWS_LIMIT, 3).build()))) { conn.setSchema(database.getSchemaName()); try (final var resultSet = conn.createStatement().executeQuery("select * from RESTAURANT")) { Assertions.assertThrows(SQLException.class, resultSet::getContinuation); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalExtension.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalExtension.java index fa6b8bc4f4f..cbf6186a120 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalExtension.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalExtension.java @@ -62,6 +62,9 @@ public class EmbeddedRelationalExtension implements RelationalExtension, BeforeE private final Options options; private StoreCatalog storeCatalog; private FDBDatabase database; + // null means "use FDB's default cluster file" (see FDBDatabaseFactory#getDatabase(String)); this mirrors + // FDBTestEnvironment#randomClusterFile()'s real, genuinely-nullable contract. + @Nullable private final String clusterFile; private final boolean register; @@ -76,7 +79,7 @@ public EmbeddedRelationalExtension(final Options options) { // storeCatalog and database are initialized by setup() (called from beforeEach()), which JUnit guarantees // to run before any other method on this extension is used. @SuppressWarnings("NullAway.Init") - public EmbeddedRelationalExtension(final String clusterFile, final boolean register, final Options options) { + public EmbeddedRelationalExtension(@Nullable final String clusterFile, final boolean register, final Options options) { final RelationalKeyspaceProvider keyspaceProvider = RelationalKeyspaceProvider.instance(); keyspaceProvider.registerDomainIfNotExists("TEST"); this.keySpace = keyspaceProvider.getKeySpace(); @@ -123,7 +126,7 @@ public EmbeddedRelationalDriver getDriver(final FormatVersion formatVersion) thr return new EmbeddedRelationalDriver(makeEngine(database, formatVersion)); } - private void makeDatabase(String clusterFile) throws RelationalException { + private void makeDatabase(@Nullable String clusterFile) throws RelationalException { database = FDBDatabaseFactory.instance().getDatabase(clusterFile); try (var connection = new DirectFdbConnection(database); Transaction txn = connection.getTransactionManager().createTransaction(Options.NONE)) { diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/OptionScopeTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/OptionScopeTest.java index ce8c92d5aea..50ebefd5e26 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/OptionScopeTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/OptionScopeTest.java @@ -38,6 +38,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.util.Objects; public class OptionScopeTest { @@ -56,7 +57,7 @@ public class OptionScopeTest { @Test public void optionTakenFromConnection() throws SQLException, RelationalException { final var driver = (RelationalDriver) DriverManager.getDriver(db.getConnectionUri().toString()); - try (Connection conn = driver.connect(db.getConnectionUri(), Options.builder().withOption(Options.Name.DRY_RUN, true).build())) { + try (Connection conn = Objects.requireNonNull(driver.connect(db.getConnectionUri(), Options.builder().withOption(Options.Name.DRY_RUN, true).build()))) { conn.setSchema(db.getSchemaName()); try (Statement statement = conn.createStatement()) { Assertions.assertThat(statement.executeUpdate(INSERT_QUERY)).isOne(); @@ -83,7 +84,7 @@ public void optionTakenFromQuery() throws SQLException { @Test public void optionSetInConnectionButOverriddenInQuery() throws SQLException, RelationalException { final var driver = (RelationalDriver) DriverManager.getDriver(db.getConnectionUri().toString()); - try (Connection conn = driver.connect(db.getConnectionUri(), Options.builder().withOption(Options.Name.DRY_RUN, false).build())) { + try (Connection conn = Objects.requireNonNull(driver.connect(db.getConnectionUri(), Options.builder().withOption(Options.Name.DRY_RUN, false).build()))) { conn.setSchema(db.getSchemaName()); try (Statement statement = conn.createStatement()) { Assertions.assertThat(statement.executeUpdate(INSERT_QUERY_DRY_RUN)).isOne(); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/QueryLoggingTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/QueryLoggingTest.java index ae721ce286e..b42741bf098 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/QueryLoggingTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/QueryLoggingTest.java @@ -135,7 +135,7 @@ void testNoLogIfMissing() throws Exception { @Test void testRelationalConnectionOptionPreparedStatement() throws Exception { final var driver = (RelationalDriver) DriverManager.getDriver(database.getConnectionUri().toString()); - try (RelationalConnection conn = driver.connect(database.getConnectionUri(), Options.builder().withOption(Options.Name.LOG_QUERY, true).build())) { + try (RelationalConnection conn = Objects.requireNonNull(driver.connect(database.getConnectionUri(), Options.builder().withOption(Options.Name.LOG_QUERY, true).build()))) { conn.setSchema(database.getSchemaName()); try (PreparedStatement ps = conn.prepareStatement("SELECT name from restaurant where rest_no = ?")) { ps.setLong(1, 0); @@ -156,7 +156,7 @@ void testRelationalConnectionOptionPreparedStatement() throws Exception { @Test void testRelationalConnectionOptionExplicitlyDisabled() throws Exception { final var driver = (RelationalDriver) DriverManager.getDriver(database.getConnectionUri().toString()); - try (RelationalConnection conn = driver.connect(database.getConnectionUri(), Options.builder().withOption(Options.Name.LOG_QUERY, false).build())) { + try (RelationalConnection conn = Objects.requireNonNull(driver.connect(database.getConnectionUri(), Options.builder().withOption(Options.Name.LOG_QUERY, false).build()))) { conn.setSchema(database.getSchemaName()); try (PreparedStatement ps = conn.prepareStatement("SELECT name from restaurant where rest_no = ?")) { ps.setLong(1, 0); @@ -177,7 +177,7 @@ void testRelationalConnectionOptionExplicitlyDisabled() throws Exception { @Test void testRelationalConnectionSetLogOnThenOff() throws Exception { final var driver = (RelationalDriver) DriverManager.getDriver(database.getConnectionUri().toString()); - try (RelationalConnection conn = driver.connect(database.getConnectionUri(), Options.NONE)) { + try (RelationalConnection conn = Objects.requireNonNull(driver.connect(database.getConnectionUri(), Options.NONE))) { conn.setSchema(database.getSchemaName()); try (Statement stmt = conn.createStatement()) { try (ResultSet rs = stmt.executeQuery("select name from restaurant")) { @@ -210,7 +210,7 @@ void testRelationalConnectionSetLogOnThenOff() throws Exception { @Test void testRelationalConnectionSetLogIsOverriddenByQueryOption() throws Exception { final var driver = (RelationalDriver) DriverManager.getDriver(database.getConnectionUri().toString()); - try (RelationalConnection conn = driver.connect(database.getConnectionUri(), Options.NONE)) { + try (RelationalConnection conn = Objects.requireNonNull(driver.connect(database.getConnectionUri(), Options.NONE))) { conn.setSchema(database.getSchemaName()); conn.setOption(Options.Name.LOG_QUERY, false); try (PreparedStatement ps = conn.prepareStatement("SELECT name from restaurant where rest_no = ? OPTIONS(LOG QUERY)")) { @@ -228,7 +228,7 @@ void testRelationalConnectionSetLogIsOverriddenByQueryOption() throws Exception void testRelationalConnectionSetLogIsOverriddenByExecuteContinuationQueryOption() throws Exception { insertRows(); final var driver = (RelationalDriver) DriverManager.getDriver(database.getConnectionUri().toString()); - try (RelationalConnection conn = driver.connect(database.getConnectionUri(), Options.NONE)) { + try (RelationalConnection conn = Objects.requireNonNull(driver.connect(database.getConnectionUri(), Options.NONE))) { Continuation continuation; conn.setSchema(database.getSchemaName()); try (RelationalPreparedStatement ps = conn.prepareStatement("SELECT name from restaurant")) { @@ -256,7 +256,7 @@ void testRelationalConnectionSetLogIsOverriddenByExecuteContinuationQueryOption( void testRelationalConnectionSetLogWithExecuteContinuation(boolean setLogging) throws Exception { insertRows(); final var driver = (RelationalDriver) DriverManager.getDriver(database.getConnectionUri().toString()); - try (RelationalConnection conn = driver.connect(database.getConnectionUri(), Options.NONE)) { + try (RelationalConnection conn = Objects.requireNonNull(driver.connect(database.getConnectionUri(), Options.NONE))) { Continuation continuation; conn.setSchema(database.getSchemaName()); try (RelationalPreparedStatement ps = conn.prepareStatement("SELECT name from restaurant")) { @@ -300,7 +300,7 @@ void testLogQueryBecauseQueryIsSlow() throws Exception { } Assertions.assertThat(logAppender.getLogEvents()).isEmpty(); final var driver = (RelationalDriver) DriverManager.getDriver(database.getConnectionUri().toString()); - try (RelationalConnection conn = driver.connect(database.getConnectionUri(), Options.builder().withOption(Options.Name.LOG_SLOW_QUERY_THRESHOLD_MICROS, 1L).build())) { + try (RelationalConnection conn = Objects.requireNonNull(driver.connect(database.getConnectionUri(), Options.builder().withOption(Options.Name.LOG_SLOW_QUERY_THRESHOLD_MICROS, 1L).build()))) { conn.setSchema(database.getSchemaName()); try (PreparedStatement ps = conn.prepareStatement("SELECT NAME FROM RESTAURANT")) { try (ResultSet rs = ps.executeQuery()) { @@ -318,7 +318,7 @@ void testLogQueryBecauseQueryIsSlowRemovesLiterals() throws Exception { } Assertions.assertThat(logAppender.getLogEvents()).isEmpty(); final var driver = (RelationalDriver) DriverManager.getDriver(database.getConnectionUri().toString()); - try (RelationalConnection conn = driver.connect(database.getConnectionUri(), Options.builder().withOption(Options.Name.LOG_SLOW_QUERY_THRESHOLD_MICROS, 1L).build())) { + try (RelationalConnection conn = Objects.requireNonNull(driver.connect(database.getConnectionUri(), Options.builder().withOption(Options.Name.LOG_SLOW_QUERY_THRESHOLD_MICROS, 1L).build()))) { conn.setSchema(database.getSchemaName()); try (PreparedStatement ps = conn.prepareStatement("SELECT * FROM RESTAURANT WHERE \"NAME\" = 'restaurant 1'")) { try (ResultSet rs = ps.executeQuery()) { diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/QueryPropertiesTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/QueryPropertiesTest.java index 7f837257673..10783545b19 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/QueryPropertiesTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/QueryPropertiesTest.java @@ -48,6 +48,7 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; public class QueryPropertiesTest { @RegisterExtension @@ -93,7 +94,7 @@ void scanWithLimit() throws RelationalException, SQLException { List testScan(Options options, long firstRestNo) throws RelationalException, SQLException { final var driver = (RelationalDriver) DriverManager.getDriver(database.getConnectionUri().toString()); - try (RelationalConnection conn = driver.connect(database.getConnectionUri(), options)) { + try (RelationalConnection conn = Objects.requireNonNull(driver.connect(database.getConnectionUri(), options))) { conn.setSchema("TEST_SCHEMA"); try (RelationalStatement s = conn.createStatement()) { for (long i = 0; i < 2; i++) { diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalConnectionRule.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalConnectionRule.java index 58534c741c6..e6efe003329 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalConnectionRule.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/RelationalConnectionRule.java @@ -33,11 +33,13 @@ import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ExtensionContext; +import org.jspecify.annotations.Nullable; import java.net.URI; import java.sql.Array; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Struct; +import java.util.Objects; import java.util.function.Supplier; public class RelationalConnectionRule implements BeforeEachCallback, AfterEachCallback, RelationalConnection { @@ -86,7 +88,10 @@ public void afterEach(ExtensionContext context) throws SQLException { public void beforeEach(ExtensionContext context) throws RelationalException, SQLException { Options opt = options == null ? Options.NONE : options; final RelationalDriver driver = driverSupplier.get(); - connection = driver.connect(dbPathSupplier.get(), opt); + // RelationalDriver#connect() is genuinely @Nullable (a driver may decline a URL it doesn't handle); + // for this test rule, a null connection here means the rule is fundamentally misconfigured, so fail + // fast with a clear message rather than propagating null into the @NonNull connection field. + connection = Objects.requireNonNull(driver.connect(dbPathSupplier.get(), opt), "driver.connect() returned null connection"); if (schema != null) { connection.setSchema(schema); } @@ -179,6 +184,7 @@ public void setOption(Options.Name name, Object value) throws SQLException { } @Override + @Nullable public URI getPath() { return connection.getPath(); } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/ddl/DdlRecordLayerSchemaTemplateTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/ddl/DdlRecordLayerSchemaTemplateTest.java index 78f3263ef06..3b7ddfdb8e0 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/ddl/DdlRecordLayerSchemaTemplateTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/ddl/DdlRecordLayerSchemaTemplateTest.java @@ -46,6 +46,7 @@ import java.sql.SQLException; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Stream; @@ -198,7 +199,7 @@ void manyStructsThatDoNotDependOnEachOther() throws RelationalException, SQLExce statement.executeUpdate(template.toString()); try (RelationalResultSet resultSet = statement.executeQuery("DESCRIBE SCHEMA TEMPLATE many_structs")) { ResultSetAssert.assertThat(resultSet).hasNextRow(); - final var type = resultSet.getArray("TABLES").getResultSet(); + final var type = Objects.requireNonNull(resultSet.getArray("TABLES")).getResultSet(); Assert.that(type.next()); Assert.that(!type.next()); } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/ExecutePropertyTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/ExecutePropertyTests.java index 195993ef936..a4db265d29d 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/ExecutePropertyTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/ExecutePropertyTests.java @@ -42,6 +42,7 @@ import java.sql.DriverManager; import java.util.List; +import java.util.Objects; public class ExecutePropertyTests { @@ -100,7 +101,7 @@ void hitLimitEveryRow(Options.Name optionName, Object optionValue, int expectedR Continuation continuation = ContinuationImpl.BEGIN; long nextCorrectResult = 10L; final var driver = (RelationalDriver) DriverManager.getDriver(database.getConnectionUri().toString()); - try (var conn = driver.connect(database.getConnectionUri(), Options.builder().withOption(optionName, optionValue).build())) { + try (var conn = Objects.requireNonNull(driver.connect(database.getConnectionUri(), Options.builder().withOption(optionName, optionValue).build()))) { conn.setSchema("TEST_SCHEMA"); while (!continuation.atEnd()) { String query = continuation.atBeginning() ? "SELECT * FROM FOO" : "EXECUTE CONTINUATION ?"; @@ -138,8 +139,8 @@ void hitLimitEveryRow(Options.Name optionName, Object optionValue, int expectedR public void multipleConnectionsDoNotAffectEachOthersLimit() throws Exception { statement.executeUpdate("INSERT INTO FOO VALUES (10, '10'), (11, '11'), (12, '12'), (13, '13'), (14, '14'), (15, '15'), (16, '16')"); final var driver = (RelationalDriver) DriverManager.getDriver(database.getConnectionUri().toString()); - try (var conn1 = driver.connect(database.getConnectionUri(), Options.builder().withOption(Options.Name.EXECUTION_SCANNED_ROWS_LIMIT, 2).build()); - var conn2 = driver.connect(database.getConnectionUri(), Options.builder().withOption(Options.Name.EXECUTION_SCANNED_ROWS_LIMIT, 3).build())) { + try (var conn1 = Objects.requireNonNull(driver.connect(database.getConnectionUri(), Options.builder().withOption(Options.Name.EXECUTION_SCANNED_ROWS_LIMIT, 2).build())); + var conn2 = Objects.requireNonNull(driver.connect(database.getConnectionUri(), Options.builder().withOption(Options.Name.EXECUTION_SCANNED_ROWS_LIMIT, 3).build()))) { conn1.setSchema("TEST_SCHEMA"); conn2.setSchema("TEST_SCHEMA"); try (var ps1 = conn1.prepareStatement("SELECT * FROM FOO"); @@ -166,7 +167,7 @@ public void multipleConnectionsDoNotAffectEachOthersLimit() throws Exception { public void limitIsKeptAcrossMultipleQueriesWithinTheSameTransaction() throws Exception { statement.executeUpdate("INSERT INTO FOO VALUES (10, '10'), (11, '11'), (12, '12')"); final var driver = (RelationalDriver) DriverManager.getDriver(database.getConnectionUri().toString()); - try (var conn = driver.connect(database.getConnectionUri(), Options.builder().withOption(Options.Name.EXECUTION_SCANNED_ROWS_LIMIT, 5).build())) { + try (var conn = Objects.requireNonNull(driver.connect(database.getConnectionUri(), Options.builder().withOption(Options.Name.EXECUTION_SCANNED_ROWS_LIMIT, 5).build()))) { conn.setSchema("TEST_SCHEMA"); conn.setAutoCommit(false); try (var ps = conn.prepareStatement("SELECT * FROM FOO")) { @@ -193,7 +194,7 @@ public void limitIsKeptAcrossMultipleQueriesWithinTheSameTransaction() throws Ex public void limitIsKeptAcrossMultipleQueriesWithinTheSameTransactionSecondQueryFailsRightAway() throws Exception { statement.executeUpdate("INSERT INTO FOO VALUES (10, '10'), (11, '11'), (12, '12')"); final var driver = (RelationalDriver) DriverManager.getDriver(database.getConnectionUri().toString()); - try (var conn = driver.connect(database.getConnectionUri(), Options.builder().withOption(Options.Name.EXECUTION_SCANNED_ROWS_LIMIT, 1).build())) { + try (var conn = Objects.requireNonNull(driver.connect(database.getConnectionUri(), Options.builder().withOption(Options.Name.EXECUTION_SCANNED_ROWS_LIMIT, 1).build()))) { conn.setSchema("TEST_SCHEMA"); conn.setAutoCommit(false); try (var ps = conn.prepareStatement("SELECT * FROM FOO")) { @@ -215,7 +216,7 @@ public void limitIsKeptAcrossMultipleQueriesWithinTheSameTransactionSecondQueryF public void limitIsResetWithNewTransaction() throws Exception { statement.executeUpdate("INSERT INTO FOO VALUES (10, '10'), (11, '11')"); final var driver = (RelationalDriver) DriverManager.getDriver(database.getConnectionUri().toString()); - try (var conn = driver.connect(database.getConnectionUri(), Options.builder().withOption(Options.Name.EXECUTION_SCANNED_ROWS_LIMIT, 5).build())) { + try (var conn = Objects.requireNonNull(driver.connect(database.getConnectionUri(), Options.builder().withOption(Options.Name.EXECUTION_SCANNED_ROWS_LIMIT, 5).build()))) { conn.setSchema("TEST_SCHEMA"); conn.setAutoCommit(false); try (var ps = conn.prepareStatement("SELECT * FROM FOO")) { diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/UpdateTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/UpdateTest.java index cea0d3e77e2..e1b2f105ae3 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/UpdateTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/UpdateTest.java @@ -49,6 +49,7 @@ import java.sql.SQLException; import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.function.Function; public class UpdateTest { @@ -229,7 +230,7 @@ private NonnullPair updateWithScanRowLimit(final String f var continuation = continuationAndNumUpdated.getLeft(); var updatedUpTill = continuationAndNumUpdated.getRight(); final var driver = (RelationalDriver) DriverManager.getDriver(database.getConnectionUri().toString()); - try (final var con = (EmbeddedRelationalConnection) driver.connect(database.getConnectionUri(), options)) { + try (final var con = (EmbeddedRelationalConnection) Objects.requireNonNull(driver.connect(database.getConnectionUri(), options))) { con.setSchema(database.getSchemaName()); final var statement = prepareUpdate(con, fieldToUpdate, updateValue.apply(con), continuation); try (final var resultSet = statement.executeQuery()) { From 0d73dc6fc6e630fe84526e0f4a050a4f6e240747 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Sun, 6 Sep 2026 22:47:04 +0100 Subject: [PATCH 38/42] Fix 14 more NullAway test-source errors in fdb-relational-core - ExplainTests, ExpressionTests: Debugger#setDebugger(Debugger) is documented to accept null (removes the current debugger) but its parameter isn't annotated @Nullable in fdb-record-layer-core; that upstream annotation gap is outside this fix's scope, so isolate the necessary suppression in a small wrapper (ExplainTests) / directly on the one call site (ExpressionTests) rather than at every call. - CaseSensitivityQueryTests: Objects.requireNonNull around a genuinely-nullable RelationalStruct column value before dereferencing it. - V2PlanGeneratorTests: same pattern, and de-duplicate repeated getStruct("i")/ getStruct("loc") calls into local variables. --- .../query/CaseSensitivityQueryTests.java | 3 ++- .../recordlayer/query/ExplainTests.java | 26 +++++++++++++------ .../recordlayer/query/ExpressionTests.java | 4 +++ .../query/V2PlanGeneratorTests.java | 17 +++++++----- 4 files changed, 35 insertions(+), 15 deletions(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/CaseSensitivityQueryTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/CaseSensitivityQueryTests.java index 1a053215dc2..1a72b61c414 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/CaseSensitivityQueryTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/CaseSensitivityQueryTests.java @@ -33,6 +33,7 @@ import org.junit.jupiter.params.provider.ValueSource; import java.net.URI; import java.sql.SQLException; +import java.util.Objects; public class CaseSensitivityQueryTests { @@ -144,7 +145,7 @@ private static void verifyResultSet(final RelationalResultSet resultSet) throws Assertions.assertTrue(resultSet.next()); Assertions.assertEquals(1, resultSet.getLong(1)); Assertions.assertEquals("bla", resultSet.getString(2)); - final var struct = resultSet.getStruct(3); + final var struct = Objects.requireNonNull(resultSet.getStruct(3)); Assertions.assertEquals("addr", struct.getString(1)); Assertions.assertEquals("a", struct.getString(2)); Assertions.assertEquals("b", struct.getString(3)); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/ExplainTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/ExplainTests.java index bdb5b4c5e2c..99318e2f7a3 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/ExplainTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/ExplainTests.java @@ -38,6 +38,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; +import org.jspecify.annotations.Nullable; import java.net.URI; import java.sql.SQLException; import java.sql.Types; @@ -67,6 +68,15 @@ public ExplainTests() { Utils.enableCascadesDebugger(); } + // Debugger#setDebugger(Debugger) is documented to accept null (it removes the current debugger; see its + // Javadoc and body in fdb-record-layer-core), but its parameter is not annotated @Nullable there. That's + // an upstream annotation gap in a module outside this fix's scope, not a real bug at these call sites, so + // isolate the one necessary suppression here rather than at each call site below. + @SuppressWarnings("NullAway") + private static void setDebugger(@Nullable Debugger debugger) { + Debugger.setDebugger(debugger); + } + @Test void explainResultSetMetadataTest() throws Exception { final var expectedLabels = List.of("PLAN", "PLAN_HASH", "PLAN_DOT", "PLAN_GML", "PLAN_CONTINUATION", "PLANNER_METRICS"); @@ -168,7 +178,7 @@ void explainContainsEventStatsWithADebuggerInstalled() throws Exception { void explainContainsEventStats() throws Exception { final var defaultDebugger = Debugger.getDebugger(); try { - Debugger.setDebugger(null); + setDebugger(null); org.junit.jupiter.api.Assertions.assertNull(Debugger.getDebugger()); try (var ddl = Ddl.builder().database(URI.create("/TEST/QT")).relationalExtension(relationalExtension).schemaTemplate(schemaTemplate).build()) { @@ -191,7 +201,7 @@ void explainContainsEventStats() throws Exception { } } } finally { - Debugger.setDebugger(defaultDebugger); + setDebugger(defaultDebugger); } } @@ -200,7 +210,7 @@ void explainDoesNotContainEventStats() throws Exception { final var defaultDebugger = Debugger.getDebugger(); final var defaultStatsCollector = PlannerEventStatsCollector.getCollector(); try { - Debugger.setDebugger(null); + setDebugger(null); PlannerEventStatsCollector.setCollector(new PlannerEventStatsCollector() { @Override public void onQuery(final String queryAsString, final com.apple.foundationdb.record.query.plan.cascades.PlanContext planContext) { @@ -240,7 +250,7 @@ public java.util.Optional Date: Sun, 6 Sep 2026 22:50:02 +0100 Subject: [PATCH 39/42] Fix 20 more NullAway test-source errors in fdb-relational-core StandardQueryTests and PreparedStatementTests dereference RelationalResultSet#getArray()/ getStruct() results (both genuinely @Nullable per RelationalStruct's real contract) without a null check. Wrap with Objects.requireNonNull() at each call site; these are test assertions where a null result would indicate the test itself is broken, so failing fast with a clear message is correct. --- .../query/PreparedStatementTests.java | 5 +- .../recordlayer/query/StandardQueryTests.java | 47 ++++++++++--------- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/PreparedStatementTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/PreparedStatementTests.java index 6c0560e0567..59580789e0b 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/PreparedStatementTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/PreparedStatementTests.java @@ -57,6 +57,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.function.BiConsumer; import java.util.stream.Stream; @@ -812,13 +813,13 @@ private Array createTagArray(RelationalConnection connection, Object[][] restaur } private void assertTags(RelationalResultSet resultSet, Object[][] restaurantTagAttributes) throws SQLException { - RelationalArray array = resultSet.getArray("tags"); + RelationalArray array = Objects.requireNonNull(resultSet.getArray("tags")); int i = 0; try (RelationalResultSet arrResultSet = array.getResultSet()) { while (arrResultSet.next()) { Assertions.assertThat(arrResultSet.getInt("INDEX")) .isEqualTo(i + 1); - var struct = arrResultSet.getStruct("VALUE"); + var struct = Objects.requireNonNull(arrResultSet.getStruct("VALUE")); try (AutoCloseableSoftAssertions softly = new AutoCloseableSoftAssertions()) { softly.assertThat(struct.getString("TAG")) .isEqualTo(restaurantTagAttributes[i][0]); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/StandardQueryTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/StandardQueryTests.java index 5ec686e63ad..671de5e3885 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/StandardQueryTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/StandardQueryTests.java @@ -162,7 +162,7 @@ void simpleSelect() throws Exception { ResultSetAssert.assertThat(resultSet).hasNextRow() .isRowPartly(insertedRecord); // explicitly test when nullable array is set to empty list, the RelationalArray object holds an empty iterable - Assertions.assertEquals("[]", resultSet.getArray("REVIEWS").toString()); + Assertions.assertEquals("[]", Objects.requireNonNull(resultSet.getArray("REVIEWS")).toString()); // explicitly test unset Nullable array is NULL Assertions.assertNull(resultSet.getArray("TAGS")); Assertions.assertNull(resultSet.getArray("CUSTOMER")); @@ -182,9 +182,9 @@ void simpleSelectWithNonNullableArrays() throws Exception { ResultSetAssert.assertThat(resultSet).hasNextRow() .isRowPartly(insertedRecord); // explicitly test when a Non-nullable array is unset, the RelationalArray object holds an empty iterable - Assertions.assertEquals("[]", resultSet.getArray("REVIEWS").toString()); - Assertions.assertEquals("[]", resultSet.getArray("TAGS").toString()); - Assertions.assertEquals("[]", resultSet.getArray("CUSTOMER").toString()); + Assertions.assertEquals("[]", Objects.requireNonNull(resultSet.getArray("REVIEWS")).toString()); + Assertions.assertEquals("[]", Objects.requireNonNull(resultSet.getArray("TAGS")).toString()); + Assertions.assertEquals("[]", Objects.requireNonNull(resultSet.getArray("CUSTOMER")).toString()); Assertions.assertFalse(resultSet.next()); } } @@ -1161,7 +1161,7 @@ void selectNestedStarWorks() throws Exception { Assertions.assertTrue(statement.execute("select (*) from t1")); try (final RelationalResultSet resultSet = statement.getResultSet()) { Assertions.assertTrue(resultSet.next()); - final var struct = resultSet.getStruct(1); + final var struct = Objects.requireNonNull(resultSet.getStruct(1)); Assertions.assertEquals(42, struct.getInt(1)); Assertions.assertEquals(100, struct.getInt(2)); Assertions.assertEquals(101, struct.getInt(3)); @@ -1170,8 +1170,8 @@ void selectNestedStarWorks() throws Exception { Assertions.assertTrue(statement.execute("select ((*)) from t1")); try (final RelationalResultSet resultSet = statement.getResultSet()) { Assertions.assertTrue(resultSet.next()); - final var struct = resultSet.getStruct(1); - final var nestedStruct = struct.getStruct(1); + final var struct = Objects.requireNonNull(resultSet.getStruct(1)); + final var nestedStruct = Objects.requireNonNull(struct.getStruct(1)); Assertions.assertEquals(42, nestedStruct.getInt(1)); Assertions.assertEquals(100, nestedStruct.getInt(2)); Assertions.assertEquals(101, nestedStruct.getInt(3)); @@ -1190,9 +1190,9 @@ void testNamingStruct() throws Exception { Assertions.assertTrue(statement.execute("select struct asd (a, 42, struct def (b, c)) as X from t1")); try (final RelationalResultSet resultSet = statement.getResultSet()) { Assertions.assertTrue(resultSet.next()); - Assertions.assertEquals("ASD", resultSet.getStruct(1).getMetaData().getTypeName()); - final var thirdCol = resultSet.getStruct(1).getStruct(3); - Assertions.assertEquals("DEF", thirdCol.getMetaData().getTypeName()); + Assertions.assertEquals("ASD", Objects.requireNonNull(resultSet.getStruct(1)).getMetaData().getTypeName()); + final var thirdCol = Objects.requireNonNull(resultSet.getStruct(1)).getStruct(3); + Assertions.assertEquals("DEF", Objects.requireNonNull(thirdCol).getMetaData().getTypeName()); Assertions.assertFalse(resultSet.next()); } } @@ -1208,12 +1208,12 @@ void testNamingStructsSameType() throws Exception { Assertions.assertTrue(statement.execute("select struct asd (a, 42, struct def (b, c), struct def(b, c)) as X from t1")); try (final RelationalResultSet resultSet = statement.getResultSet()) { Assertions.assertTrue(resultSet.next()); - Assertions.assertEquals("ASD", resultSet.getStruct(1).getMetaData().getTypeName()); + Assertions.assertEquals("ASD", Objects.requireNonNull(resultSet.getStruct(1)).getMetaData().getTypeName()); Assertions.assertEquals("X", resultSet.getMetaData().getColumnLabel(1)); - final var thirdCol = resultSet.getStruct(1).getStruct(3); - Assertions.assertEquals("DEF", thirdCol.getMetaData().getTypeName()); - final var fourthCol = resultSet.getStruct(1).getStruct(4); - Assertions.assertEquals("DEF", fourthCol.getMetaData().getTypeName()); + final var thirdCol = Objects.requireNonNull(resultSet.getStruct(1)).getStruct(3); + Assertions.assertEquals("DEF", Objects.requireNonNull(thirdCol).getMetaData().getTypeName()); + final var fourthCol = Objects.requireNonNull(resultSet.getStruct(1)).getStruct(4); + Assertions.assertEquals("DEF", Objects.requireNonNull(fourthCol).getMetaData().getTypeName()); Assertions.assertFalse(resultSet.next()); } } @@ -1243,10 +1243,10 @@ void testNamingStructsSameTypeDifferentNestingLevels() throws Exception { try (final RelationalResultSet resultSet = statement.getResultSet()) { Assertions.assertTrue(resultSet.next()); final var col3 = resultSet.getStruct(3); - Assertions.assertEquals("DEF", col3.getMetaData().getTypeName()); - final var col44 = resultSet.getStruct(4).getStruct(4); + Assertions.assertEquals("DEF", Objects.requireNonNull(col3).getMetaData().getTypeName()); + final var col44 = Objects.requireNonNull(resultSet.getStruct(4)).getStruct(4); Assertions.assertEquals("X", resultSet.getMetaData().getColumnLabel(4)); - Assertions.assertEquals("DEF", col44.getMetaData().getTypeName()); + Assertions.assertEquals("DEF", Objects.requireNonNull(col44).getMetaData().getTypeName()); Assertions.assertFalse(resultSet.next()); } } @@ -1671,7 +1671,7 @@ void testSelectWithConstructedArrayOfPrimitives() throws Exception { "Did not return a result set from a select statement!"); try (final RelationalResultSet resultSet = statement.getResultSet()) { ResultSetAssert.assertThat(resultSet).hasNextRow(); - try (RelationalResultSet arrResultSet = resultSet.getArray(1).getResultSet()) { + try (RelationalResultSet arrResultSet = Objects.requireNonNull(resultSet.getArray(1)).getResultSet()) { ResultSetAssert.assertThat(arrResultSet).hasNextRow(); Assertions.assertEquals("testName", arrResultSet.getString(2)); Assertions.assertEquals(DatabaseMetaData.columnNoNulls, arrResultSet.getMetaData().isNullable(2)); @@ -1692,11 +1692,12 @@ void testSelectWithConstructedArrayOfStructs() throws Exception { "Did not return a result set from a select statement!"); try (final RelationalResultSet resultSet = statement.getResultSet()) { ResultSetAssert.assertThat(resultSet).hasNextRow(); - try (RelationalResultSet arrResultSet = resultSet.getArray(1).getResultSet()) { + try (RelationalResultSet arrResultSet = Objects.requireNonNull(resultSet.getArray(1)).getResultSet()) { ResultSetAssert.assertThat(arrResultSet).hasNextRow(); - Assertions.assertEquals("address", arrResultSet.getStruct(2).getString("ADDRESS")); - Assertions.assertEquals("1", arrResultSet.getStruct(2).getString("LATITUDE")); - Assertions.assertEquals("1", arrResultSet.getStruct(2).getString("LONGITUDE")); + final var struct2 = Objects.requireNonNull(arrResultSet.getStruct(2)); + Assertions.assertEquals("address", struct2.getString("ADDRESS")); + Assertions.assertEquals("1", struct2.getString("LATITUDE")); + Assertions.assertEquals("1", struct2.getString("LONGITUDE")); Assertions.assertEquals(DatabaseMetaData.columnNoNulls, arrResultSet.getMetaData().isNullable(2)); } Assertions.assertFalse(resultSet.next()); From d19f8360bddea60febc039089327d776c66967f0 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Sun, 6 Sep 2026 22:55:31 +0100 Subject: [PATCH 40/42] Fix final 36 NullAway test-source errors in fdb-relational-core (StructDataMetadataTest) RelationalResultSet#getStruct()/getArray() are genuinely @Nullable per RelationalStruct's real contract; wrap chained/dereferenced calls with Objects.requireNonNull(), or add the matching Assertions.assertNotNull() JUnit already uses elsewhere in this file (NullAway recognizes it as a narrowing assertion) where a reassignment lacked one. This completes :fdb-relational-core:compileTestJava, which is now clean, in addition to :fdb-relational-core:compileJava fixed in earlier commits on this branch. --- .../recordlayer/StructDataMetadataTest.java | 61 ++++++++++--------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/StructDataMetadataTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/StructDataMetadataTest.java index 227727285d2..ade32e7862b 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/StructDataMetadataTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/StructDataMetadataTest.java @@ -250,7 +250,7 @@ private void canReadStructTypeName(String query, ThrowingConsumer { - RelationalStruct struct = resultSet.getStruct(1).getStruct("ST1"); + RelationalStruct struct = Objects.requireNonNull(Objects.requireNonNull(resultSet.getStruct(1)).getStruct("ST1")); Assertions.assertEquals("STRUCT_1", struct.getMetaData().getTypeName()); }); } @@ -258,9 +258,9 @@ void canReadProjectedStructTypeNameInNestedStar() throws Throwable { @Test void canReadProjectedNestedStructTypeNameInNestedStar() throws Throwable { canReadStructTypeName("SELECT (*) FROM NT", resultSet -> { - RelationalStruct struct = resultSet.getStruct(1).getStruct("ST1"); + RelationalStruct struct = Objects.requireNonNull(Objects.requireNonNull(resultSet.getStruct(1)).getStruct("ST1")); Assertions.assertEquals("STRUCT_2", struct.getMetaData().getTypeName()); - RelationalStruct nestedStruct = struct.getStruct("D"); + RelationalStruct nestedStruct = Objects.requireNonNull(struct.getStruct("D")); Assertions.assertEquals("STRUCT_1", nestedStruct.getMetaData().getTypeName()); }); } @@ -268,7 +268,7 @@ void canReadProjectedNestedStructTypeNameInNestedStar() throws Throwable { @Test void canReadProjectedStructInArrayTypeNameInNestedStar() throws Throwable { canReadStructTypeName("SELECT (*) FROM AT", resultSet -> { - RelationalArray array = resultSet.getStruct(1).getArray("ST2"); + RelationalArray array = Objects.requireNonNull(Objects.requireNonNull(resultSet.getStruct(1)).getArray("ST2")); Assertions.assertEquals("STRUCT", array.getMetaData().getElementTypeName()); Assertions.assertEquals("STRUCT_3", array.getMetaData().getElementStructMetaData().getTypeName()); }); @@ -277,7 +277,7 @@ void canReadProjectedStructInArrayTypeNameInNestedStar() throws Throwable { @Test void canReadProjectedStructTypeNameInUnnestedStar() throws Throwable { canReadStructTypeName("SELECT * FROM T", resultSet -> { - RelationalStruct struct = resultSet.getStruct("ST1"); + RelationalStruct struct = Objects.requireNonNull(resultSet.getStruct("ST1")); Assertions.assertEquals("STRUCT_1", struct.getMetaData().getTypeName()); }); } @@ -285,9 +285,9 @@ void canReadProjectedStructTypeNameInUnnestedStar() throws Throwable { @Test void canReadProjectedNestedStructTypeNameInUnnestedStar() throws Throwable { canReadStructTypeName("SELECT * FROM NT", resultSet -> { - RelationalStruct struct = resultSet.getStruct("ST1"); + RelationalStruct struct = Objects.requireNonNull(resultSet.getStruct("ST1")); Assertions.assertEquals("STRUCT_2", struct.getMetaData().getTypeName()); - RelationalStruct nestedStruct = struct.getStruct("D"); + RelationalStruct nestedStruct = Objects.requireNonNull(struct.getStruct("D")); Assertions.assertEquals("STRUCT_1", nestedStruct.getMetaData().getTypeName()); }); } @@ -295,7 +295,7 @@ void canReadProjectedNestedStructTypeNameInUnnestedStar() throws Throwable { @Test void canReadProjectedStructInArrayTypeNameInUnnestedStar() throws Throwable { canReadStructTypeName("SELECT * FROM AT", resultSet -> { - RelationalArray array = resultSet.getArray("ST2"); + RelationalArray array = Objects.requireNonNull(resultSet.getArray("ST2")); Assertions.assertEquals("STRUCT", array.getMetaData().getElementTypeName()); Assertions.assertEquals("STRUCT_3", array.getMetaData().getElementStructMetaData().getTypeName()); }); @@ -304,7 +304,7 @@ void canReadProjectedStructInArrayTypeNameInUnnestedStar() throws Throwable { @Test void canReadProjectedStructTypeNameDirectlyProjected() throws Throwable { canReadStructTypeName("SELECT ST1 FROM T", resultSet -> { - RelationalStruct struct = resultSet.getStruct("ST1"); + RelationalStruct struct = Objects.requireNonNull(resultSet.getStruct("ST1")); Assertions.assertEquals("STRUCT_1", struct.getMetaData().getTypeName()); }); } @@ -312,7 +312,7 @@ void canReadProjectedStructTypeNameDirectlyProjected() throws Throwable { @Test void canReadProjectedNestedStructTypeNameDirectlyProjected() throws Throwable { canReadStructTypeName("SELECT ST1 FROM NT", resultSet -> { - RelationalStruct struct = resultSet.getStruct("ST1").getStruct("D"); + RelationalStruct struct = Objects.requireNonNull(Objects.requireNonNull(resultSet.getStruct("ST1")).getStruct("D")); Assertions.assertEquals("STRUCT_1", struct.getMetaData().getTypeName()); }); } @@ -320,7 +320,7 @@ void canReadProjectedNestedStructTypeNameDirectlyProjected() throws Throwable { @Test void canReadProjectedStructInArrayTypeNameDirectlyProjected() throws Throwable { canReadStructTypeName("SELECT * FROM AT", resultSet -> { - RelationalArray array = resultSet.getArray("ST2"); + RelationalArray array = Objects.requireNonNull(resultSet.getArray("ST2")); Assertions.assertEquals("STRUCT", array.getMetaData().getElementTypeName()); Assertions.assertEquals("STRUCT_3", array.getMetaData().getElementStructMetaData().getTypeName()); }); @@ -329,35 +329,35 @@ void canReadProjectedStructInArrayTypeNameDirectlyProjected() throws Throwable { @Test void canReadProjectedDynamicStruct() throws Throwable { canReadStructTypeName("SELECT STRUCT STRUCT_6(name, st1.a, st1) FROM T", resultSet -> { - RelationalStruct struct = resultSet.getStruct(1); + RelationalStruct struct = Objects.requireNonNull(resultSet.getStruct(1)); Assertions.assertEquals("STRUCT_6", struct.getMetaData().getTypeName()); - Assertions.assertEquals("STRUCT_1", struct.getStruct(3).getMetaData().getTypeName()); + Assertions.assertEquals("STRUCT_1", Objects.requireNonNull(struct.getStruct(3)).getMetaData().getTypeName()); }); } @Test void canReadProjectedStructWithDynamicStructInside() throws Throwable { canReadStructTypeName("SELECT STRUCT STRUCT_6(name, STRUCT STRUCT_7(name, st1.a)) FROM T", resultSet -> { - RelationalStruct struct = resultSet.getStruct(1); + RelationalStruct struct = Objects.requireNonNull(resultSet.getStruct(1)); Assertions.assertEquals("STRUCT_6", struct.getMetaData().getTypeName()); - Assertions.assertEquals("STRUCT_7", struct.getStruct(2).getMetaData().getTypeName()); + Assertions.assertEquals("STRUCT_7", Objects.requireNonNull(struct.getStruct(2)).getMetaData().getTypeName()); }); } @Test void canReadAnonymousStructWithDynamicStructInside() throws Throwable { canReadStructTypeName("SELECT (name, STRUCT STRUCT_7(name, st1.a)) FROM T", resultSet -> { - RelationalStruct struct = resultSet.getStruct(1); - Assertions.assertEquals("STRUCT_7", struct.getStruct(2).getMetaData().getTypeName()); + RelationalStruct struct = Objects.requireNonNull(resultSet.getStruct(1)); + Assertions.assertEquals("STRUCT_7", Objects.requireNonNull(struct.getStruct(2)).getMetaData().getTypeName()); }); } @Disabled // https://github.com/FoundationDB/fdb-record-layer/issues/3794 void canDistinguishFieldsOfStructurallyEqualTypes() throws Throwable { canReadStructTypeName("SELECT * FROM T4", resultSet -> { - RelationalStruct struct1 = resultSet.getStruct("N1"); + RelationalStruct struct1 = Objects.requireNonNull(resultSet.getStruct("N1")); Assertions.assertEquals("N1", struct1.getMetaData().getTypeName()); - RelationalStruct struct2 = resultSet.getStruct("N2"); + RelationalStruct struct2 = Objects.requireNonNull(resultSet.getStruct("N2")); Assertions.assertEquals("N2", struct2.getMetaData().getTypeName()); }); } @@ -365,11 +365,11 @@ void canDistinguishFieldsOfStructurallyEqualTypes() throws Throwable { @Disabled // https://github.com/FoundationDB/fdb-record-layer/issues/3794 void canDistinguishNestedFieldsOfStructurallyEqualTypes() throws Throwable { canReadStructTypeName("SELECT * FROM T3", resultSet -> { - RelationalStruct struct = resultSet.getStruct("M"); + RelationalStruct struct = Objects.requireNonNull(resultSet.getStruct("M")); Assertions.assertEquals("M", struct.getMetaData().getTypeName()); - RelationalStruct struct1 = struct.getStruct("X"); + RelationalStruct struct1 = Objects.requireNonNull(struct.getStruct("X")); Assertions.assertEquals("N1", struct1.getMetaData().getTypeName()); - RelationalStruct struct2 = struct.getStruct("Y"); + RelationalStruct struct2 = Objects.requireNonNull(struct.getStruct("Y")); Assertions.assertEquals("N2", struct2.getMetaData().getTypeName()); }); } @@ -407,6 +407,7 @@ void canReadNestedStruct() throws Exception { Assertions.assertEquals("Goodbye", nestedStruct.getString("A"), "Incorrect doubly-nested struct"); //use get object to make sure it returns the correct type nestedStruct = (RelationalStruct) struct.getObject(2); + Assertions.assertNotNull(nestedStruct); Assertions.assertEquals("Goodbye", nestedStruct.getString(1), "Incorrect doubly-nested struct"); Assertions.assertEquals("Goodbye", nestedStruct.getString("A"), "Incorrect doubly-nested struct"); } @@ -426,6 +427,7 @@ void canReadRepeatedStruct() throws Exception { try (var arrayRs = st2.getResultSet()) { Assertions.assertTrue(arrayRs.next(), "No array records returned!"); var struct = arrayRs.getStruct(2); + Assertions.assertNotNull(struct, "Struct is missing!"); Assertions.assertArrayEquals("Hello".getBytes(StandardCharsets.UTF_8), struct.getBytes(1), "Incorrect bytes column!"); Assertions.assertArrayEquals("Hello".getBytes(StandardCharsets.UTF_8), struct.getBytes("C"), "Incorrect bytes column!"); @@ -434,6 +436,7 @@ void canReadRepeatedStruct() throws Exception { Assertions.assertTrue(arrayRs.next(), "too few array records returned!"); struct = arrayRs.getStruct(2); + Assertions.assertNotNull(struct, "Struct is missing!"); Assertions.assertArrayEquals("Bonjour".getBytes(StandardCharsets.UTF_8), struct.getBytes(1), "Incorrect bytes column!"); Assertions.assertArrayEquals("Bonjour".getBytes(StandardCharsets.UTF_8), struct.getBytes("C"), "Incorrect bytes column!"); @@ -477,7 +480,7 @@ void canReadRepeatedStructWithArray() throws SQLException { @Test void structTypeMetadataPreservedAcrossPlanCache() throws Throwable { canReadStructTypeName("SELECT * FROM T WHERE NAME = 'test_record_1'", resultSet -> { - RelationalStruct struct = resultSet.getStruct("ST1"); + RelationalStruct struct = Objects.requireNonNull(resultSet.getStruct("ST1")); Assertions.assertEquals("STRUCT_1", struct.getMetaData().getTypeName(), "Struct type name should be preserved across plan cache"); }, 2, 0); @@ -486,8 +489,8 @@ void structTypeMetadataPreservedAcrossPlanCache() throws Throwable { @Test void nestedStructTypeMetadataPreservedAcrossPlanCache() throws Throwable { canReadStructTypeName("SELECT * FROM NT WHERE T_NAME = 'nt_record'", resultSet -> { - RelationalStruct struct = resultSet.getStruct("ST1"); - RelationalStruct nestedStruct = struct.getStruct("D"); + RelationalStruct struct = Objects.requireNonNull(resultSet.getStruct("ST1")); + RelationalStruct nestedStruct = Objects.requireNonNull(struct.getStruct("D")); Assertions.assertEquals("STRUCT_1", nestedStruct.getMetaData().getTypeName(), "Nested struct type name should be preserved across plan cache"); }, 2, 0); @@ -496,7 +499,7 @@ void nestedStructTypeMetadataPreservedAcrossPlanCache() throws Throwable { @Test void arrayStructTypeMetadataPreservedAcrossPlanCache() throws Throwable { canReadStructTypeName("SELECT * FROM AT WHERE A_NAME = 'a_test_rec'", resultSet -> { - RelationalArray array = resultSet.getArray("ST2"); + RelationalArray array = Objects.requireNonNull(resultSet.getArray("ST2")); Assertions.assertEquals("STRUCT_3", array.getMetaData().getElementStructMetaData().getTypeName(), "Array element struct type name should be preserved across plan cache"); }, 2, 0); @@ -505,7 +508,7 @@ void arrayStructTypeMetadataPreservedAcrossPlanCache() throws Throwable { @Test void structTypeMetadataPreservedInContinuationAcrossPlanCache() throws Throwable { canReadStructTypeName("SELECT * FROM T", resultSet -> { - RelationalStruct struct = resultSet.getStruct("ST1"); + RelationalStruct struct = Objects.requireNonNull(resultSet.getStruct("ST1")); Assertions.assertEquals("STRUCT_1", struct.getMetaData().getTypeName(), "Struct type name should be preserved in continuation across plan cache"); }, 1, 2); @@ -514,9 +517,9 @@ void structTypeMetadataPreservedInContinuationAcrossPlanCache() throws Throwable @Test void nestedStructTypeMetadataPreservedInContinuationAcrossPlanCache() throws Throwable { canReadStructTypeName("SELECT * FROM NT", resultSet -> { - RelationalStruct struct = resultSet.getStruct("ST1"); + RelationalStruct struct = Objects.requireNonNull(resultSet.getStruct("ST1")); Assertions.assertEquals("STRUCT_2", struct.getMetaData().getTypeName()); - RelationalStruct nestedStruct = struct.getStruct("D"); + RelationalStruct nestedStruct = Objects.requireNonNull(struct.getStruct("D")); Assertions.assertEquals("STRUCT_1", nestedStruct.getMetaData().getTypeName(), "Nested struct type name should be preserved in continuation across plan cache"); }, 1, 2); From cf4ba4860f1b2c9d63a41e07f61ef712eaa0891e Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Sun, 6 Sep 2026 23:11:44 +0100 Subject: [PATCH 41/42] Fix 13 NullAway errors in fdb-relational-core jmh benchmarks Apply the established @SuppressWarnings("NullAway.Init") convention to benchmark state fields that are populated by JMH's @Setup/@Param lifecycle (or an equivalent up()/init() method) rather than by the constructor: EmbeddedRelationalBenchmark.Driver, BenchmarkConnHolder, SimplePlanCachingBenchmark, RelationalScanBenchmark (and its nested RelationalConnHolder), IndexScanVsQueryBenchmark, and SetSchemaBenchmark.RelationalConnHolder. Mark EmbeddedRelationalBenchmark.Driver#planCache and SimplePlanCachingBenchmark#getPlanCache() as @Nullable to reflect their real, already-supported contract: a null plan cache is a meaningful value ("no cache configured") that RecordLayerEngine already accepts as @Nullable. Suppress the RecordLayerScanBenchmark#scan() NullAway false positive on the null continuation passed to scanRecords(), using the same "byte[] nullability isn't tracked reliably" rationale and pattern already established in IndexingMultiTargetByRecords. --- .../relational/api/SetSchemaBenchmark.java | 4 ++++ .../relational/recordlayer/BenchmarkConnHolder.java | 4 ++++ .../recordlayer/EmbeddedRelationalBenchmark.java | 11 ++++++++--- .../recordlayer/IndexScanVsQueryBenchmark.java | 4 ++++ .../recordlayer/RecordLayerScanBenchmark.java | 3 +++ .../recordlayer/RelationalScanBenchmark.java | 8 ++++++++ .../recordlayer/SimplePlanCachingBenchmark.java | 7 ++++++- 7 files changed, 37 insertions(+), 4 deletions(-) diff --git a/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/api/SetSchemaBenchmark.java b/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/api/SetSchemaBenchmark.java index dcd3eb79d5a..699f3253f48 100644 --- a/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/api/SetSchemaBenchmark.java +++ b/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/api/SetSchemaBenchmark.java @@ -101,6 +101,10 @@ public static void main(String[] args) throws RunnerException { } @State(Scope.Thread) + // NullAway.Init is suppressed here because connection follows the standard JMH benchmark + // lifecycle: it is left unset by the constructor and is always populated by init() (a @Setup + // method) before any benchmark method that uses it runs. + @SuppressWarnings("NullAway.Init") public static class RelationalConnHolder { private Connection connection; diff --git a/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/BenchmarkConnHolder.java b/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/BenchmarkConnHolder.java index 0694e5db401..74b71d33ee3 100644 --- a/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/BenchmarkConnHolder.java +++ b/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/BenchmarkConnHolder.java @@ -32,6 +32,10 @@ * Shared JMH thread-scoped connection holder for relational benchmarks. * Subclasses supply the database URI and schema; this class manages the connection lifecycle. */ +// NullAway.Init is suppressed here because connection follows the standard JMH benchmark +// lifecycle: it is left unset by the constructor and is always populated by init() (a @Setup +// method) before any benchmark method that uses it runs. +@SuppressWarnings("NullAway.Init") abstract class BenchmarkConnHolder { protected final URI dbUri; diff --git a/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalBenchmark.java b/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalBenchmark.java index 7c8a6a18e03..c733760d845 100644 --- a/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalBenchmark.java +++ b/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalBenchmark.java @@ -35,6 +35,7 @@ import com.apple.foundationdb.relational.recordlayer.catalog.StoreCatalogProvider; import com.apple.foundationdb.relational.recordlayer.ddl.RecordLayerMetadataOperationsFactory; import com.apple.foundationdb.relational.recordlayer.query.cache.RelationalPlanCache; +import org.jspecify.annotations.Nullable; import org.openjdk.jmh.annotations.Level; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.State; @@ -68,6 +69,10 @@ public abstract class EmbeddedRelationalBenchmark { static final String schemaTemplateName = "RestaurantTemplate"; + // NullAway.Init is suppressed here because driver/keySpace/fdbDatabase/catalog follow the + // standard JMH benchmark lifecycle: they are left unset by the constructor and are always + // populated by up() before any benchmark method that uses them runs. + @SuppressWarnings("NullAway.Init") public static class Driver { RelationalDriver driver; KeySpace keySpace; @@ -76,7 +81,7 @@ public static class Driver { private final String templateName; private final String templateDef; - private final RelationalPlanCache planCache; + private final @Nullable RelationalPlanCache planCache; public StoreCatalog catalog; @@ -84,7 +89,7 @@ public Driver() { this(schemaTemplateName, templateDefinition); } - public Driver(RelationalPlanCache planCache) { + public Driver(@Nullable RelationalPlanCache planCache) { this(schemaTemplateName, templateDefinition, planCache); } @@ -94,7 +99,7 @@ public Driver(String templateName, String templateDef) { this.planCache = null; } - public Driver(String templateName, String templateDef, RelationalPlanCache planCache) { + public Driver(String templateName, String templateDef, @Nullable RelationalPlanCache planCache) { this.templateName = templateName; this.templateDef = templateDef; this.planCache = planCache; diff --git a/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/IndexScanVsQueryBenchmark.java b/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/IndexScanVsQueryBenchmark.java index 22eaf5f7185..eb291b5a88d 100644 --- a/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/IndexScanVsQueryBenchmark.java +++ b/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/IndexScanVsQueryBenchmark.java @@ -85,6 +85,10 @@ @OutputTimeUnit(TimeUnit.MILLISECONDS) @State(Scope.Benchmark) @API(API.Status.EXPERIMENTAL) +// NullAway.Init is suppressed here because indexHintLabel/indexHintCategory follow the standard +// JMH benchmark lifecycle: they are left unset by the constructor and are always populated by +// trialUp() (a @Setup method) before any benchmark method that uses them runs. +@SuppressWarnings("NullAway.Init") public class IndexScanVsQueryBenchmark extends EmbeddedRelationalBenchmark { static final String schema = "bench"; diff --git a/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/RecordLayerScanBenchmark.java b/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/RecordLayerScanBenchmark.java index 315b72404f7..954865f2a92 100644 --- a/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/RecordLayerScanBenchmark.java +++ b/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/RecordLayerScanBenchmark.java @@ -67,6 +67,9 @@ @API(API.Status.EXPERIMENTAL) public class RecordLayerScanBenchmark extends RelationalScanBenchmark { + // NullAway does not reliably track @Nullable on byte[] parameters, so it flags the (legitimate) + // null continuation argument to scanRecords below even though that method declares it @Nullable. + @SuppressWarnings("NullAway") @Override public void scan(Blackhole bh, RelationalConnHolder ignored) throws RelationalException { FDBDatabase fdbDb = FDBDatabaseFactory.instance().getDatabase(); diff --git a/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/RelationalScanBenchmark.java b/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/RelationalScanBenchmark.java index 45190f43906..e940443cf2c 100644 --- a/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/RelationalScanBenchmark.java +++ b/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/RelationalScanBenchmark.java @@ -70,6 +70,10 @@ @OutputTimeUnit(TimeUnit.MILLISECONDS) @State(Scope.Benchmark) @API(API.Status.EXPERIMENTAL) +// NullAway.Init is suppressed here because accessor follows the standard JMH benchmark lifecycle: +// it is left unset by the constructor and is always populated by trialUp() (a @Setup method) +// before any benchmark method that uses it runs. +@SuppressWarnings("NullAway.Init") public class RelationalScanBenchmark extends EmbeddedRelationalBenchmark { static final String schema = "putAndScan"; @@ -182,6 +186,10 @@ public static void main(String[] args) throws RunnerException { } @State(Scope.Thread) + // NullAway.Init is suppressed here because connection follows the standard JMH benchmark + // lifecycle: it is left unset by the constructor and is always populated by init() (a @Setup + // method) before any benchmark method that uses it runs. + @SuppressWarnings("NullAway.Init") public static class RelationalConnHolder { private Connection connection; diff --git a/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/SimplePlanCachingBenchmark.java b/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/SimplePlanCachingBenchmark.java index fed79214034..1d28d87b99f 100644 --- a/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/SimplePlanCachingBenchmark.java +++ b/fdb-relational-core/src/jmh/java/com/apple/foundationdb/relational/recordlayer/SimplePlanCachingBenchmark.java @@ -29,6 +29,7 @@ import com.apple.foundationdb.relational.api.exceptions.RelationalException; import com.apple.foundationdb.relational.recordlayer.query.cache.RelationalPlanCache; import com.apple.foundationdb.relational.recordlayer.util.ExceptionUtil; +import org.jspecify.annotations.Nullable; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -74,6 +75,10 @@ @Threads(Threads.MAX) @OutputTimeUnit(TimeUnit.MILLISECONDS) @API(API.Status.EXPERIMENTAL) +// NullAway.Init is suppressed here because cacheType/driver follow the standard JMH benchmark +// lifecycle: cacheType is populated by JMH via @Param reflection and driver is populated by +// trialUp() (a @Setup method), not by the constructor. +@SuppressWarnings("NullAway.Init") public class SimplePlanCachingBenchmark extends EmbeddedRelationalBenchmark { static final String dbName = "/BENCHMARKS/SimplePlanCaching"; @@ -124,7 +129,7 @@ public void repeatedRead(Blackhole bh) throws SQLException { } } - private RelationalPlanCache getPlanCache() { + private @Nullable RelationalPlanCache getPlanCache() { switch (cacheType) { case "NONE": return null; From 0526e8c6676c48243a3a56c51ed7188da2c6c348 Mon Sep 17 00:00:00 2001 From: Arnaud Lacurie Date: Mon, 7 Sep 2026 23:24:08 +0100 Subject: [PATCH 42/42] Fix 14 SpotBugs NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE findings in fdb-relational-core Widened @Nullable contracts elsewhere in the rollout (EmbeddedRelationalConnection, NonnullPair-returning helpers, CompatibleTypeEvolutionPredicate.FieldAccessTrieNode) let SpotBugs's interprocedural analysis see real null-dereference paths that were previously masked by now-redundant @Nonnull annotations. Fix each with an explicit Objects.requireNonNull() or by capturing a nullable getter's result in a single local variable instead of calling it twice (once to null-check, once to dereference). Also remove the now-useless @SpotBugsSuppressWarnings("NP_METHOD_PARAMETER_TIGHTENS_ANNOTATION") on EmbeddedRelationalStruct$Builder: its justification (fdb-relational-core still using javax.annotation.Nullable while fdb-relational-api used jspecify's) no longer applies now that this class uses org.jspecify.annotations.Nullable too. --- .../relational/api/EmbeddedRelationalStruct.java | 2 -- .../relational/recordlayer/CatalogMetaData.java | 3 ++- .../relational/recordlayer/query/CopyPlan.java | 5 +++-- .../query/ddl/MaterializedViewIndexGenerator.java | 3 ++- .../recordlayer/query/visitors/DdlVisitor.java | 9 ++++++--- .../query/visitors/ExpressionVisitor.java | 14 +++++++------- .../query/visitors/MetadataPlanVisitor.java | 5 ++++- .../recordlayer/query/visitors/QueryVisitor.java | 7 ++++--- .../relational/recordlayer/util/TypeUtils.java | 9 +++++---- 9 files changed, 33 insertions(+), 24 deletions(-) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalStruct.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalStruct.java index e52af0b3ba9..7db9d90cf9d 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalStruct.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalStruct.java @@ -22,7 +22,6 @@ import com.apple.foundationdb.relational.api.metadata.DataType; import com.apple.foundationdb.relational.recordlayer.ArrayRow; -import com.apple.foundationdb.relational.util.SpotBugsSuppressWarnings; import org.jspecify.annotations.Nullable; @@ -37,7 +36,6 @@ static RelationalStructBuilder newBuilder() { return new Builder(); } - @SpotBugsSuppressWarnings(value = "NP_METHOD_PARAMETER_TIGHTENS_ANNOTATION", justification = "False positive: RelationalStructBuilder's parameters are jspecify @Nullable (fdb-relational-api), while this class still uses javax.annotation.Nullable (fdb-relational-core not yet migrated); SpotBugs does not recognize the two annotations as equivalent across the module boundary, including on the covariant-return bridge methods synthesized for addString/addUuid/addObject, which it can't otherwise be annotated.") class Builder implements RelationalStructBuilder { final List fields = new ArrayList<>(); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/CatalogMetaData.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/CatalogMetaData.java index a17b22c220d..710ee589b6a 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/CatalogMetaData.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/CatalogMetaData.java @@ -53,6 +53,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; @@ -72,7 +73,7 @@ public CatalogMetaData(EmbeddedRelationalConnection conn, StoreCatalog catalog) @Override public RelationalResultSet getSchemas() throws SQLException { - return getSchemas(conn.getPath().getPath(), null); + return getSchemas(Objects.requireNonNull(conn.getPath()).getPath(), null); } @Override diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java index 7d6389fb4dd..248aaf901fe 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/CopyPlan.java @@ -79,6 +79,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; /** @@ -435,7 +436,7 @@ private static void importCatalogInfo(CatalogInfo catalogInfo, final int templateVersion = catalogInfo.getTemplateVersion(); final NonnullPair databaseAndSchema = getDatabaseAndSchema(dataPath); - final URI databaseUri = databaseAndSchema.getLeft(); + final URI databaseUri = Objects.requireNonNull(databaseAndSchema.getLeft()); final String schemaName = databaseAndSchema.getRight(); try { @@ -590,7 +591,7 @@ private static NonnullPair getDatabaseAndSchema(final KeySpacePath pathString = "/" + pathString; } final NonnullPair, String> uri = SemanticAnalyzer.parseSchemaURI(pathString); - final Optional database = uri.getLeft(); + final Optional database = Objects.requireNonNull(uri.getLeft()); if (database.isEmpty()) { throw new RelationalException("Invalid COPY path: " + pathString, ErrorCode.INVALID_PATH); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/MaterializedViewIndexGenerator.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/MaterializedViewIndexGenerator.java index bcc76fde80b..895e2e20542 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/MaterializedViewIndexGenerator.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/ddl/MaterializedViewIndexGenerator.java @@ -228,7 +228,8 @@ public RecordLayerIndex.Builder generate(RecordLayerSchemaTemplate.Builder schem final var indexExpressionAndType = generateAggregateIndexKeyExpression(aggregateValue, groupingKeyExpression); final String indexType = Objects.requireNonNull(indexExpressionAndType.getRight()); indexBuilder.setIndexType(indexType); - indexBuilder.setKeyExpression(KeyExpression.fromProto(NullableArrayUtils.wrapArray(indexExpressionAndType.getLeft().toKeyExpression(), tableType, containsNullableArray))); + final var indexKeyExpressionValue = Objects.requireNonNull(indexExpressionAndType.getLeft()); + indexBuilder.setKeyExpression(KeyExpression.fromProto(NullableArrayUtils.wrapArray(indexKeyExpressionValue.toKeyExpression(), tableType, containsNullableArray))); if (IndexTypes.PERMUTED_MIN.equals(indexType) || IndexTypes.PERMUTED_MAX.equals(indexType)) { int permutedSize = aggregateOrderIndex < 0 ? 0 : (fieldValues.size() - aggregateOrderIndex); indexBuilder.setOption(IndexOptions.PERMUTED_SIZE_OPTION, permutedSize); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/DdlVisitor.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/DdlVisitor.java index 0afcc739815..4d98225962d 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/DdlVisitor.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/DdlVisitor.java @@ -70,6 +70,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.function.BiConsumer; @@ -551,7 +552,8 @@ public ProceduralPlan visitCreateSchemaStatement(RelationalParser.CreateSchemaSt final Identifier schemaId = visitUid(ctx.schemaId().path().uid()); final var dbAndSchema = SemanticAnalyzer.parseSchemaIdentifier(schemaId); final var templateId = visitUid(ctx.schemaTemplateId().uid()); - return ProceduralPlan.of(metadataOperationsFactory.getCreateSchemaConstantAction(dbAndSchema.getLeft().orElse(dbUri), + final Optional databaseUri = Objects.requireNonNull(dbAndSchema.getLeft()); + return ProceduralPlan.of(metadataOperationsFactory.getCreateSchemaConstantAction(databaseUri.orElse(dbUri), dbAndSchema.getRight(), templateId.getName(), Options.NONE)); } @@ -574,8 +576,9 @@ public ProceduralPlan visitDropDatabaseStatement(RelationalParser.DropDatabaseSt public ProceduralPlan visitDropSchemaStatement(RelationalParser.DropSchemaStatementContext ctx) { final var schemaId = visitUid(ctx.uid()); final var dbAndSchema = SemanticAnalyzer.parseSchemaIdentifier(schemaId); - Assert.thatUnchecked(dbAndSchema.getLeft().isPresent(), ErrorCode.UNKNOWN_DATABASE, () -> String.format(Locale.ROOT, "invalid database identifier in '%s'", ctx.uid().getText())); - return ProceduralPlan.of(metadataOperationsFactory.getDropSchemaConstantAction(dbAndSchema.getLeft().get(), dbAndSchema.getRight(), Options.NONE)); + final Optional databaseUri = Objects.requireNonNull(dbAndSchema.getLeft()); + Assert.thatUnchecked(databaseUri.isPresent(), ErrorCode.UNKNOWN_DATABASE, () -> String.format(Locale.ROOT, "invalid database identifier in '%s'", ctx.uid().getText())); + return ProceduralPlan.of(metadataOperationsFactory.getDropSchemaConstantAction(databaseUri.get(), dbAndSchema.getRight(), Options.NONE)); } @Override diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/ExpressionVisitor.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/ExpressionVisitor.java index 7d3419eaa87..3abd0e8da91 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/ExpressionVisitor.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/ExpressionVisitor.java @@ -222,9 +222,9 @@ public OrderByExpression visitOrderByExpression(RelationalParser.OrderByExpressi public NonnullPair visitInlineTableDefinition(RelationalParser.InlineTableDefinitionContext ctx) { final var tableId = visitTableName(ctx.tableName()); final var columnIdTrie = visitUidListWithNestingsInParens(ctx.uidListWithNestingsInParens()); - int columnCount = Objects.requireNonNull(columnIdTrie.getThis().getChildrenMap()).size(); - final var columnsList = new ArrayList<>(Collections.nCopies(columnCount, (RecordLayerColumn) null)); - for (final var entry : columnIdTrie.getThis().getChildrenMap().entrySet()) { + final var childrenMap = Objects.requireNonNull(columnIdTrie.getThis().getChildrenMap()); + final var columnsList = new ArrayList<>(Collections.nCopies(childrenMap.size(), (RecordLayerColumn) null)); + for (final var entry : childrenMap.entrySet()) { final var column = toColumn(entry.getKey(), entry.getValue()); columnsList.set(column.getIndex(), column); } @@ -238,12 +238,12 @@ private static RecordLayerColumn toColumn(FieldValue.ResolvedAccessor field, Com // null, even though ResolvedAccessor.getName() is declared @Nullable in general. final var columnName = Objects.requireNonNull(field.getName(), "inline table column must have a name"); final var builder = RecordLayerColumn.newBuilder().setName(columnName).setIndex(field.getOrdinal()); - if (columnIdTrie.getChildrenMap() == null) { + final var childrenMap = columnIdTrie.getChildrenMap(); + if (childrenMap == null) { return builder.setDataType(DataTypeUtils.toRelationalType(field.getType())).build(); } - int columnCount = columnIdTrie.getChildrenMap().size(); - final var fields = new ArrayList<>(Collections.nCopies(columnCount, (DataType.StructType.Field) null)); - for (final var child : columnIdTrie.getChildrenMap().entrySet()) { + final var fields = new ArrayList<>(Collections.nCopies(childrenMap.size(), (DataType.StructType.Field) null)); + for (final var child : childrenMap.entrySet()) { final var column = toColumn(child.getKey(), child.getValue()); fields.set(column.getIndex(), DataType.StructType.Field.from(column.getName(), column.getDataType(), column.getIndex())); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/MetadataPlanVisitor.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/MetadataPlanVisitor.java index 467a43d8351..34b15e1e213 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/MetadataPlanVisitor.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/MetadataPlanVisitor.java @@ -26,6 +26,8 @@ import com.apple.foundationdb.relational.recordlayer.query.QueryPlan; import com.apple.foundationdb.relational.recordlayer.query.SemanticAnalyzer; import java.net.URI; +import java.util.Objects; +import java.util.Optional; @API(API.Status.EXPERIMENTAL) public final class MetadataPlanVisitor extends DelegatingVisitor { @@ -60,7 +62,8 @@ public QueryPlan.MetadataQueryPlan visitSimpleDescribeSchemaStatement(Relational final var ddlFactory = getDelegate().getDdlQueryFactory(); final var schemaId = visitUid(ctx.schemaId().path().uid()); final var dbAndSchema = SemanticAnalyzer.parseSchemaIdentifier(schemaId); - final var database = dbAndSchema.getLeft().orElse(getDelegate().getDbUri()); + final Optional databaseUri = Objects.requireNonNull(dbAndSchema.getLeft()); + final var database = databaseUri.orElse(getDelegate().getDbUri()); final var schema = dbAndSchema.getRight(); return QueryPlan.MetadataQueryPlan.of(ddlFactory.getDescribeSchemaQueryAction(database, schema)); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/QueryVisitor.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/QueryVisitor.java index 0a9d64f860c..2dcf8fa1ec2 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/QueryVisitor.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/QueryVisitor.java @@ -203,7 +203,7 @@ public LogicalOperator handleRecursiveNamedQuery(final RelationalParser.NamedQue final var partitions = getDelegate().getSemanticAnalyzer().partitionRecursiveQuery(recursiveQueryContext.query(), queryName, getDelegate()::visitFullId, memoized, this); final var nonRecursiveBranches = partitions.getLeft(); - final var recursiveBranches = partitions.getRight(); + final var recursiveBranches = Objects.requireNonNull(partitions.getRight()); getDelegate().popPlanFragment(); if (recursiveBranches.isEmpty()) { return visitNamedQuery(recursiveQueryContext); @@ -769,12 +769,13 @@ public LogicalOperator visitInsertStatement(RelationalParser.InsertStatementCont } private static StringTrieNode toString(CompatibleTypeEvolutionPredicate.FieldAccessTrieNode fieldAccessTrieNode) { - if (fieldAccessTrieNode.getChildrenMap() == null) { + final var childrenMap = fieldAccessTrieNode.getChildrenMap(); + if (childrenMap == null) { return StringTrieNode.leafNode(); } // pair.getKey() is always constructed from an Identifier's name (see ExpressionVisitor#visitUidListWithNestings), // which is never null, even though ResolvedAccessor.getName() is declared @Nullable in general. - final var map = fieldAccessTrieNode.getChildrenMap().entrySet().stream().collect(ImmutableMap.toImmutableMap( + final var map = childrenMap.entrySet().stream().collect(ImmutableMap.toImmutableMap( pair -> Objects.requireNonNull(pair.getKey().getName()), pair -> toString(pair.getValue()))); return new StringTrieNode(map); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/TypeUtils.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/TypeUtils.java index 56f534884f7..7ccf7bd81b6 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/TypeUtils.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/util/TypeUtils.java @@ -47,7 +47,8 @@ private static Type setFieldNamesInternal(final Type input, if (input.isPrimitive()) { return input; } - if (trie.getChildrenMap() != null && trie.getChildrenMap().isEmpty()) { + final var childrenMap = trie.getChildrenMap(); + if (childrenMap != null && childrenMap.isEmpty()) { return input; } if (input.isArray()) { @@ -67,8 +68,8 @@ final var record = (Type.Record)input; final var newlyNamedFields = ImmutableList.builder(); // A record's trie node always has a populated children map -- one entry per field -- which is // exactly what we index into below. - final var childrenMap = Objects.requireNonNull(trie.getChildrenMap(), "record type's field-access trie node has no children map"); - final var fieldAliases = new ArrayList<>(childrenMap.keySet()); + final var nonNullChildrenMap = Objects.requireNonNull(childrenMap, "record type's field-access trie node has no children map"); + final var fieldAliases = new ArrayList<>(nonNullChildrenMap.keySet()); Assert.thatUnchecked(fieldAliases.size() == recordFields.size(), ErrorCode.INCOMPATIBLE_TABLE_ALIAS, () -> "number of record fields mismatch"); fieldAliases.sort(Comparator.comparingInt(FieldValue.ResolvedAccessor::getOrdinal)); @@ -77,7 +78,7 @@ final var record = (Type.Record)input; final var recordField = recordFields.get(i); // fieldAlias is one of childrenMap's own keys (drawn from childrenMap.keySet() above), so this // lookup always finds a value. - final var fieldTrie = Objects.requireNonNull(childrenMap.get(fieldAlias)); + final var fieldTrie = Objects.requireNonNull(nonNullChildrenMap.get(fieldAlias)); final var renamedFieldType = setFieldNamesInternal(recordField.getFieldType(), fieldTrie); final var newField = Type.Record.Field.of(renamedFieldType, Optional.ofNullable(fieldAlias.getName()), Optional.of(recordField.getFieldIndex()));