From c9a69dbe5116d0493c5a867edb650b44ac1eeb7d Mon Sep 17 00:00:00 2001 From: Byron Ellis Date: Tue, 12 Aug 2025 01:25:48 -0700 Subject: [PATCH 1/8] Add vscode settings to .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 1ed91e41d3..84a1cc3f30 100644 --- a/.gitignore +++ b/.gitignore @@ -100,3 +100,6 @@ hs_err_pid* # macOS *.DS_Store + +# VSCode +.vscode/settings.json From 309b5ca52d944a36b52dea2cff469d9a153f6b2f Mon Sep 17 00:00:00 2001 From: Byron Ellis Date: Tue, 12 Aug 2025 01:26:58 -0700 Subject: [PATCH 2/8] Use the Google Cloud Libraries BOM instead of the Storage specific BOM. Storage is included as the larger libraries BOM and the version matches the desired Storage version. --- gradle/libs.versions.toml | 2 +- gradle/projects.main.properties | 1 + polaris-core/build.gradle.kts | 2 +- runtime/service/build.gradle.kts | 4 ++-- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ea4ed51611..d23af44531 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -49,7 +49,7 @@ commons-lang3 = { module = "org.apache.commons:commons-lang3", version = "3.18.0 commons-text = { module = "org.apache.commons:commons-text", version = "1.14.0" } eclipselink = { module = "org.eclipse.persistence:eclipselink", version = "4.0.7" } errorprone = { module = "com.google.errorprone:error_prone_core", version = "2.41.0" } -google-cloud-storage-bom = { module = "com.google.cloud:google-cloud-storage-bom", version = "2.55.0" } +google-cloud-libraries-bom = { module = "com.google.cloud:libraries-bom", version = "26.64.0" } guava = { module = "com.google.guava:guava", version = "33.4.8-jre" } h2 = { module = "com.h2database:h2", version = "2.3.232" } dnsjava = { module = "dnsjava:dnsjava", version = "3.6.3" } diff --git a/gradle/projects.main.properties b/gradle/projects.main.properties index 39ab227411..c078b07267 100644 --- a/gradle/projects.main.properties +++ b/gradle/projects.main.properties @@ -34,6 +34,7 @@ polaris-runtime-common=runtime/common polaris-runtime-test-common=runtime/test-common polaris-eclipselink=persistence/eclipselink polaris-relational-jdbc=persistence/relational-jdbc +polaris-google-cloud-spanner=persistence/google-cloud-spanner polaris-tests=integration-tests aggregated-license-report=aggregated-license-report polaris-immutables=tools/immutables diff --git a/polaris-core/build.gradle.kts b/polaris-core/build.gradle.kts index e963673b57..044ba5848b 100644 --- a/polaris-core/build.gradle.kts +++ b/polaris-core/build.gradle.kts @@ -98,7 +98,7 @@ dependencies { } implementation("org.apache.iceberg:iceberg-gcp") - implementation(platform(libs.google.cloud.storage.bom)) + implementation(platform(libs.google.cloud.libraries.bom)) implementation("com.google.cloud:google-cloud-storage") testCompileOnly(project(":polaris-immutables")) diff --git a/runtime/service/build.gradle.kts b/runtime/service/build.gradle.kts index 6a3cc092b9..57ac5324a0 100644 --- a/runtime/service/build.gradle.kts +++ b/runtime/service/build.gradle.kts @@ -95,7 +95,7 @@ dependencies { compileOnly(libs.jakarta.annotation.api) compileOnly(libs.spotbugs.annotations) - implementation(platform(libs.google.cloud.storage.bom)) + implementation(platform(libs.google.cloud.libraries.bom)) implementation("com.google.cloud:google-cloud-storage") implementation(platform(libs.awssdk.bom)) implementation("software.amazon.awssdk:sts") @@ -174,7 +174,7 @@ dependencies { testFixturesImplementation("org.apache.iceberg:iceberg-core") testFixturesImplementation("org.apache.iceberg:iceberg-aws") - testFixturesImplementation(platform(libs.google.cloud.storage.bom)) + testFixturesImplementation(platform(libs.google.cloud.libraries.bom)) testFixturesImplementation("com.google.cloud:google-cloud-storage") testFixturesImplementation(platform(libs.awssdk.bom)) testFixturesImplementation("software.amazon.awssdk:sts") From 09c4d42ee3ed6b654b290e33ac9e9a656cbf7798 Mon Sep 17 00:00:00 2001 From: Byron Ellis Date: Tue, 12 Aug 2025 01:28:36 -0700 Subject: [PATCH 3/8] Add the initial implementation of the Spanner DAO for review. This commit defines the overall Spanner schema with Realm as the parent table for all entities. This is the minimum needed to bootstrap a realm. --- .../google-cloud-spanner/build.gradle.kts | 42 +++++ .../GoogleCloudSpannerConfiguration.java | 33 ++++ ...SpannerDatabaseClientLifecycleManager.java | 143 +++++++++++++++++ .../relational/spanner/model/Realm.java | 36 +++++ .../relational/spanner/util/Modifier.java | 57 +++++++ .../relational/spanner/util/SpannerUtil.java | 150 ++++++++++++++++++ .../polaris/persistence/spanner/schema-v1.sql | 86 ++++++++++ 7 files changed, 547 insertions(+) create mode 100644 persistence/google-cloud-spanner/build.gradle.kts create mode 100644 persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerConfiguration.java create mode 100644 persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java create mode 100644 persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/model/Realm.java create mode 100644 persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/Modifier.java create mode 100644 persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/SpannerUtil.java create mode 100644 persistence/google-cloud-spanner/src/main/resources/org/apache/polaris/persistence/spanner/schema-v1.sql diff --git a/persistence/google-cloud-spanner/build.gradle.kts b/persistence/google-cloud-spanner/build.gradle.kts new file mode 100644 index 0000000000..02a99ed411 --- /dev/null +++ b/persistence/google-cloud-spanner/build.gradle.kts @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +plugins { + id("polaris-server") + alias(libs.plugins.jandex) +} + +dependencies { + implementation(project(":polaris-core")) + implementation(libs.slf4j.api) + implementation(libs.guava) + + implementation(platform(libs.google.cloud.libraries.bom)) + implementation("com.google.cloud:google-cloud-spanner") + + compileOnly(libs.jakarta.annotation.api) + compileOnly(libs.jakarta.enterprise.cdi.api) + compileOnly(libs.jakarta.inject.api) + + implementation(libs.smallrye.common.annotation) // @Identifier + + testImplementation(libs.mockito.junit.jupiter) + testImplementation(libs.h2) + testImplementation(testFixtures(project(":polaris-core"))) +} diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerConfiguration.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerConfiguration.java new file mode 100644 index 0000000000..17a215ad6d --- /dev/null +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerConfiguration.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +package org.apache.polaris.persistence.relational.spanner; + +import java.util.Optional; + +public interface GoogleCloudSpannerConfiguration { + + public Optional projectId(); + + public Optional instanceId(); + + public Optional databaseId(); + + public Optional emulatorHost(); +} diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java new file mode 100644 index 0000000000..60ea387b0d --- /dev/null +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +package org.apache.polaris.persistence.relational.spanner; + +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerException; +import com.google.common.collect.ImmutableList; +import jakarta.annotation.PostConstruct; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.function.Consumer; +import java.util.function.Supplier; +import org.apache.polaris.core.context.RealmContext; +import org.apache.polaris.core.persistence.bootstrap.SchemaOptions; +import org.apache.polaris.persistence.relational.spanner.model.Realm; +import org.apache.polaris.persistence.relational.spanner.util.SpannerUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@ApplicationScoped +public class GoogleCloudSpannerDatabaseClientLifecycleManager { + + private static Logger LOGGER = + LoggerFactory.getLogger(GoogleCloudSpannerDatabaseClientLifecycleManager.class); + + @Inject GoogleCloudSpannerConfiguration spannerConfiguration; + + protected Spanner spanner; + protected DatabaseId databaseId; + + @PostConstruct + protected void init() { + spanner = SpannerUtil.spannerFromConfiguration(spannerConfiguration); + databaseId = SpannerUtil.databaseFromConfiguration(spannerConfiguration); + } + + protected List getSpannerDatabaseDdl(SchemaOptions options) { + final InputStream schemaStream; + if (options.schemaFile() != null) { + try { + schemaStream = new FileInputStream(options.schemaFile()); + } catch (IOException e) { + throw new IllegalArgumentException("Unable to load file " + options.schemaFile(), e); + } + } else { + if (options.schemaVersion() == null || options.schemaVersion() == 1) { + schemaStream = + getClass().getResourceAsStream("/org/apache/polaris/persistence/spanner/schema-v1.sql"); + } else { + throw new IllegalArgumentException("Unknown schema version " + options.schemaVersion()); + } + } + try (schemaStream) { + String schema = new String(schemaStream.readAllBytes(), Charset.forName("UTF-8")); + List lines = new ArrayList<>(); + for (String s : schema.split("\n")) { + s = s.trim(); + if (s.startsWith("--") || s.length() == 0) { + continue; + } + lines.add(s); + } + return List.of(String.join(" ", lines).split(";")); + } catch (IOException e) { + throw new RuntimeException("Unable to retrieve DDL statements", e); + } + } + + @Produces + public Consumer getSchemaInitializer() { + return (options) -> { + List ddlStatements = getSpannerDatabaseDdl(options); + LOGGER.info( + "Attempting to initialize Spanner database DDL with {} statements,", + ddlStatements.size()); + DatabaseAdminClient client = spanner.getDatabaseAdminClient(); + Database dbInfo = + client.newDatabaseBuilder(databaseId).setDialect(Dialect.GOOGLE_STANDARD_SQL).build(); + try { + spanner.getDatabaseAdminClient().updateDatabaseDdl(dbInfo, ddlStatements, null).get(); + LOGGER.info("Successfully applied DDL update."); + } catch (InterruptedException | ExecutionException e) { + LOGGER.error("Unable to update Spanner DDL.", e); + throw new RuntimeException( + "Unable to update Spanner DDL. Please disable this option for this database configuration.", + e); + } + }; + } + + @Produces + public Consumer getRealmInitializer() { + return (realmContext) -> { + try { + spanner + .getDatabaseClient(databaseId) + .write(ImmutableList.of(Realm.upsert(realmContext.getRealmIdentifier()))); + } catch (SpannerException e) { + LOGGER.error("Unable to initialize realm " + realmContext.getRealmIdentifier(), e); + } + }; + } + + @Produces + public Supplier getDatabaseClientSupplier() { + return () -> spanner.getDatabaseClient(databaseId); + } + + @Produces + public Supplier getDatabaseAdminClientSupplier() { + return () -> spanner.getDatabaseAdminClient(); + } +} diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/model/Realm.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/model/Realm.java new file mode 100644 index 0000000000..ea5498c09a --- /dev/null +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/model/Realm.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +package org.apache.polaris.persistence.relational.spanner.model; + +import com.google.cloud.spanner.Key; +import com.google.cloud.spanner.Mutation; + +public final class Realm { + + public static String TABLE_NAME = "Realms"; + + public static Mutation upsert(String realmId) { + return Mutation.newInsertOrUpdateBuilder(TABLE_NAME).set("RealmId").to(realmId).build(); + } + + public static Mutation delete(String realmId) { + return Mutation.delete(TABLE_NAME, Key.of(realmId)); + } +} diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/Modifier.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/Modifier.java new file mode 100644 index 0000000000..713d1ae5d7 --- /dev/null +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/Modifier.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +package org.apache.polaris.persistence.relational.spanner.util; + +import java.util.Optional; +import java.util.function.BiFunction; +import java.util.function.Function; + +public class Modifier { + T wrapped; + + protected Modifier(T wrapped) { + this.wrapped = wrapped; + } + + public Modifier apply(Function fn) { + wrapped = fn.apply(wrapped); + return this; + } + + public Modifier orElse(Optional toApply, V other, BiFunction fn) { + wrapped = fn.apply(wrapped, toApply.orElse(other)); + return this; + } + + public Modifier ifPresent(Optional toApply, BiFunction fn) { + if (toApply.isPresent()) { + wrapped = fn.apply(wrapped, toApply.get()); + } + return this; + } + + public T get() { + return wrapped; + } + + public static Modifier of(T value) { + return new Modifier<>(value); + } +} diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/SpannerUtil.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/SpannerUtil.java new file mode 100644 index 0000000000..7e2a7871c5 --- /dev/null +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/SpannerUtil.java @@ -0,0 +1,150 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +package org.apache.polaris.persistence.relational.spanner.util; + +import com.google.cloud.ServiceOptions; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.InstanceId; +import com.google.cloud.spanner.Key; +import com.google.cloud.spanner.KeySet; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.Struct; +import com.google.cloud.spanner.StructReader; +import com.google.cloud.spanner.Type; +import com.google.cloud.spanner.Value; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Optional; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; +import org.apache.polaris.persistence.relational.spanner.GoogleCloudSpannerConfiguration; + +public final class SpannerUtil { + + public static final String INT64_TYPE = + Type.int64().getSpannerTypeName(Dialect.GOOGLE_STANDARD_SQL); + public static final String STRING_TYPE = + Type.string().getSpannerTypeName(Dialect.GOOGLE_STANDARD_SQL); + + public static final String JSON_TYPE = + Type.json().getSpannerTypeName(Dialect.GOOGLE_STANDARD_SQL); + + private static final Gson GSON = new Gson(); + + public static Value jsonValue(Map properties) { + JsonObject jsonObject = new JsonObject(); + if (properties != null) { + properties.forEach(jsonObject::addProperty); + } + return Value.json(jsonObject.toString()); + } + + public static Map jsonMap(String properties) { + HashMap map = new HashMap<>(); + if (properties != null && !properties.isBlank()) { + JsonObject obj = GSON.fromJson(properties, JsonObject.class); + obj.asMap().forEach((k, v) -> map.put(k, v.toString())); + } + return map; + } + + public static KeySet asKeySet(Iterable keys) { + KeySet.Builder builder = KeySet.newBuilder(); + for (Key key : keys) { + builder = builder.addKey(key); + } + return builder.build(); + } + + public static Struct column( + String name, String spannerType, boolean nullable, boolean primaryKey) { + return Struct.newBuilder() + .set("Name") + .to(name) + .set("Type") + .to(spannerType) + .set("Nullable") + .to(nullable) + .set("PrimaryKey") + .to(primaryKey) + .build(); + } + + public static Optional projectFromConfiguration(GoogleCloudSpannerConfiguration config) { + if (config.databaseId().isPresent()) { + String databaseId = config.databaseId().get(); + if (databaseId.startsWith("project")) { + return Optional.ofNullable(DatabaseId.of(databaseId).getInstanceId().getProject()); + } + } + return config.projectId(); + } + + public static DatabaseId databaseFromConfiguration(GoogleCloudSpannerConfiguration config) { + String databaseId = config.databaseId().orElseThrow(); + if (databaseId.startsWith("project")) { + return DatabaseId.of(databaseId); + } + String instanceId = config.instanceId().orElseThrow(); + if (instanceId.startsWith("project")) { + return DatabaseId.of(instanceId + "/" + databaseId); + } else { + return DatabaseId.of(InstanceId.of(config.projectId().orElseThrow(), instanceId), databaseId); + } + } + + public static Spanner spannerFromConfiguration(GoogleCloudSpannerConfiguration config) { + return Modifier.of(SpannerOptions.newBuilder()) + .ifPresent(projectFromConfiguration(config), ServiceOptions.Builder::setProjectId) + .ifPresent(config.emulatorHost(), SpannerOptions.Builder::setEmulatorHost) + .get() + .build() + .getService(); + } + + public static Iterator asIterator(final ResultSet resultSet) { + return new Iterator() { + + @Override + public boolean hasNext() { + return resultSet.next(); + } + + @Override + public StructReader next() { + return resultSet; + } + }; + } + + public static Stream asStream(final ResultSet resultSet) { + + return StreamSupport.stream( + Spliterators.spliteratorUnknownSize(asIterator(resultSet), Spliterator.ORDERED), false); + } +} diff --git a/persistence/google-cloud-spanner/src/main/resources/org/apache/polaris/persistence/spanner/schema-v1.sql b/persistence/google-cloud-spanner/src/main/resources/org/apache/polaris/persistence/spanner/schema-v1.sql new file mode 100644 index 0000000000..c503a756bd --- /dev/null +++ b/persistence/google-cloud-spanner/src/main/resources/org/apache/polaris/persistence/spanner/schema-v1.sql @@ -0,0 +1,86 @@ +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file-- +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you 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. + +CREATE SEQUENCE IF NOT EXISTS Ids OPTIONS(sequence_kind = 'bit_reversed_positive'); + +CREATE TABLE IF NOT EXISTS Realms( + RealmId STRING(MAX) NOT NULL +) +PRIMARY KEY (RealmId); + +CREATE TABLE IF NOT EXISTS Entities( +RealmId STRING(MAX) NOT NULL, +CatalogId INT64 NOT NULL, +Id INT64 NOT NULL, +ParentId INT64 NOT NULL, +Name STRING(MAX), +EntityVersion INT64 NOT NULL, +TypeCode INT64 NOT NULL, +SubTypeCode INT64 NOT NULL, +CreateTimestamp INT64, +DropTimestamp INT64, +PurgeTimestamp INT64, +ToPurgeTimestamp INT64, +LastUpdateTimestamp INT64, +`Properties` JSON, +InternalProperties JSON, +GrantRecordsVersion INT64, +LocationWithoutScheme STRING(MAX)) +PRIMARY KEY (RealmId,Id), +INTERLEAVE IN PARENT Realms ON DELETE CASCADE; + +CREATE UNIQUE NULL_FILTERED INDEX IF NOT EXISTS EntityNameIndex ON Entities(RealmId,CatalogId,ParentId,TypeCode,Name); + +CREATE INDEX IF NOT EXISTS EntityChildrenIndex ON Entities(RealmId,ParentId, TypeCode); +CREATE INDEX IF NOT EXISTS EntityLocationsIndex ON Entities (RealmId, ParentId, LocationWithoutScheme) WHERE LocationWithoutScheme IS NOT NULL; + +CREATE TABLE IF NOT EXISTS GrantRecords( + RealmId STRING(MAX) NOT NULL, + SecurableCatalogId INT64 NOT NULL, + SecurableId INT64 NOT NULL, + GranteeCatalogId INT64 NOT NULL, + GranteeId INT64 NOT NULL, + PrivilegeCode INT64) +PRIMARY KEY (RealmId,SecurableCatalogId,SecurableId,GranteeCatalogId,GranteeId,PrivilegeCode), +INTERLEAVE IN PARENT Realms ON DELETE CASCADE; + +CREATE INDEX IF NOT EXISTS GrantRecordsGranteeIndex ON GrantRecords(RealmId,GranteeCatalogId,GranteeId); + +CREATE TABLE IF NOT EXISTS PrincipalAuthenticationData( + RealmId STRING(MAX) NOT NULL, + PrincipalClientId STRING(MAX) NOT NULL, + PrincipalId INT64 NOT NULL, + MainSecretHash STRING(MAX) NOT NULL, + SecondarySecretHash STRING(MAX) NOT NULL, + SecretSalt STRING(MAX) NOT NULL) +PRIMARY KEY (RealmId,PrincipalClientId,PrincipalId), +INTERLEAVE IN PARENT Realms ON DELETE CASCADE; + + +CREATE TABLE IF NOT EXISTS PolicyMapping( + RealmId STRING(MAX) NOT NULL, + TargetCatalogId INT64 NOT NULL, + TargetId INT64 NOT NULL, + PolicyTypeCode INT64 NOT NULL, + PolicyCatalogId INT64 NOT NULL, + PolicyId INT64 NOT NULL, + Parameters JSON) +PRIMARY KEY (RealmId, TargetCatalogId, TargetId, PolicyTypeCode, PolicyCatalogId, PolicyId), +INTERLEAVE IN PARENT Realms ON DELETE CASCADE; + +CREATE INDEX IF NOT EXISTS PolicyMappingPolicyIndex ON PolicyMapping(RealmId,PolicyCatalogId,PolicyId,PolicyTypeCode) STORING(Parameters); \ No newline at end of file From 6819410f7b9fd83c327b9aeec453c1371b2c6ac2 Mon Sep 17 00:00:00 2001 From: Byron Ellis Date: Tue, 12 Aug 2025 09:59:01 -0700 Subject: [PATCH 4/8] Updated in response to comments. In particular added new classes to replace the Consumer and Supplier classes to avoid potential problems with resolution. --- .../google-cloud-spanner/build.gradle.kts | 3 ++- .../spanner/DatabaseAdminClientSupplier.java | 25 +++++++++++++++++++ .../spanner/DatabaseClientSupplier.java | 25 +++++++++++++++++++ .../GoogleCloudSpannerConfiguration.java | 4 +++ ...SpannerDatabaseClientLifecycleManager.java | 16 ++++++------ .../relational/spanner/RealmInitializer.java | 25 +++++++++++++++++++ .../relational/spanner/SchemaInitializer.java | 25 +++++++++++++++++++ .../relational/spanner/util/SpannerUtil.java | 5 ++++ 8 files changed, 120 insertions(+), 8 deletions(-) create mode 100644 persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/DatabaseAdminClientSupplier.java create mode 100644 persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/DatabaseClientSupplier.java create mode 100644 persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/RealmInitializer.java create mode 100644 persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/SchemaInitializer.java diff --git a/persistence/google-cloud-spanner/build.gradle.kts b/persistence/google-cloud-spanner/build.gradle.kts index 02a99ed411..96679cd2b6 100644 --- a/persistence/google-cloud-spanner/build.gradle.kts +++ b/persistence/google-cloud-spanner/build.gradle.kts @@ -34,7 +34,8 @@ dependencies { compileOnly(libs.jakarta.enterprise.cdi.api) compileOnly(libs.jakarta.inject.api) - implementation(libs.smallrye.common.annotation) // @Identifier + compileOnly(libs.smallrye.common.annotation) // @Identifier + compileOnly(libs.smallrye.config.core) // @ConfigMapping testImplementation(libs.mockito.junit.jupiter) testImplementation(libs.h2) diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/DatabaseAdminClientSupplier.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/DatabaseAdminClientSupplier.java new file mode 100644 index 0000000000..fd578fa540 --- /dev/null +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/DatabaseAdminClientSupplier.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +package org.apache.polaris.persistence.relational.spanner; + +import com.google.cloud.spanner.DatabaseAdminClient; +import java.util.function.Supplier; + +public interface DatabaseAdminClientSupplier extends Supplier {} diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/DatabaseClientSupplier.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/DatabaseClientSupplier.java new file mode 100644 index 0000000000..748a8b1ec5 --- /dev/null +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/DatabaseClientSupplier.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +package org.apache.polaris.persistence.relational.spanner; + +import com.google.cloud.spanner.DatabaseClient; +import java.util.function.Supplier; + +public interface DatabaseClientSupplier extends Supplier {} diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerConfiguration.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerConfiguration.java index 17a215ad6d..1e220c32ed 100644 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerConfiguration.java +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerConfiguration.java @@ -19,10 +19,14 @@ package org.apache.polaris.persistence.relational.spanner; +import io.smallrye.config.ConfigMapping; import java.util.Optional; +@ConfigMapping(prefix = "polaris.persistence.spanner") public interface GoogleCloudSpannerConfiguration { + public Optional quotaProjectId(); + public Optional projectId(); public Optional instanceId(); diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java index 60ea387b0d..962e4dcd4c 100644 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java @@ -21,7 +21,6 @@ import com.google.cloud.spanner.Database; import com.google.cloud.spanner.DatabaseAdminClient; -import com.google.cloud.spanner.DatabaseClient; import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.Spanner; @@ -30,7 +29,6 @@ import jakarta.annotation.PostConstruct; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; -import jakarta.inject.Inject; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; @@ -39,7 +37,6 @@ import java.util.List; import java.util.concurrent.ExecutionException; import java.util.function.Consumer; -import java.util.function.Supplier; import org.apache.polaris.core.context.RealmContext; import org.apache.polaris.core.persistence.bootstrap.SchemaOptions; import org.apache.polaris.persistence.relational.spanner.model.Realm; @@ -53,7 +50,12 @@ public class GoogleCloudSpannerDatabaseClientLifecycleManager { private static Logger LOGGER = LoggerFactory.getLogger(GoogleCloudSpannerDatabaseClientLifecycleManager.class); - @Inject GoogleCloudSpannerConfiguration spannerConfiguration; + protected final GoogleCloudSpannerConfiguration spannerConfiguration; + + public GoogleCloudSpannerDatabaseClientLifecycleManager( + GoogleCloudSpannerConfiguration spannerConfiguration) { + this.spannerConfiguration = spannerConfiguration; + } protected Spanner spanner; protected DatabaseId databaseId; @@ -97,7 +99,7 @@ protected List getSpannerDatabaseDdl(SchemaOptions options) { } @Produces - public Consumer getSchemaInitializer() { + public SchemaInitializer getSchemaInitializer() { return (options) -> { List ddlStatements = getSpannerDatabaseDdl(options); LOGGER.info( @@ -132,12 +134,12 @@ public Consumer getRealmInitializer() { } @Produces - public Supplier getDatabaseClientSupplier() { + public DatabaseClientSupplier getDatabaseClientSupplier() { return () -> spanner.getDatabaseClient(databaseId); } @Produces - public Supplier getDatabaseAdminClientSupplier() { + public DatabaseAdminClientSupplier getDatabaseAdminClientSupplier() { return () -> spanner.getDatabaseAdminClient(); } } diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/RealmInitializer.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/RealmInitializer.java new file mode 100644 index 0000000000..0e25a99073 --- /dev/null +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/RealmInitializer.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +package org.apache.polaris.persistence.relational.spanner; + +import java.util.function.Consumer; +import org.apache.polaris.core.context.RealmContext; + +public interface RealmInitializer extends Consumer {} diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/SchemaInitializer.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/SchemaInitializer.java new file mode 100644 index 0000000000..494a0d1ea9 --- /dev/null +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/SchemaInitializer.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +package org.apache.polaris.persistence.relational.spanner; + +import java.util.function.Consumer; +import org.apache.polaris.core.persistence.bootstrap.SchemaOptions; + +public interface SchemaInitializer extends Consumer {} diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/SpannerUtil.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/SpannerUtil.java index 7e2a7871c5..03cfd8b9eb 100644 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/SpannerUtil.java +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/SpannerUtil.java @@ -96,6 +96,11 @@ public static Struct column( } public static Optional projectFromConfiguration(GoogleCloudSpannerConfiguration config) { + // If the quota project is set use that. + if (config.quotaProjectId().isPresent()) { + return config.quotaProjectId(); + } + if (config.databaseId().isPresent()) { String databaseId = config.databaseId().get(); if (databaseId.startsWith("project")) { From 5ee86ee85be20d175a400a118d8ba52a1dd9d7d8 Mon Sep 17 00:00:00 2001 From: Byron Ellis Date: Tue, 12 Aug 2025 17:45:32 -0700 Subject: [PATCH 5/8] Addressing more reviewer comments --- ...SpannerDatabaseClientLifecycleManager.java | 54 +++++++------------ .../relational/spanner/RealmInitializer.java | 25 --------- .../relational/spanner/model/Realm.java | 2 +- .../relational/spanner/util/Modifier.java | 2 +- .../relational/spanner/util/SpannerUtil.java | 1 - 5 files changed, 20 insertions(+), 64 deletions(-) delete mode 100644 persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/RealmInitializer.java diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java index 962e4dcd4c..de3e2fe6f3 100644 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java @@ -19,16 +19,6 @@ package org.apache.polaris.persistence.relational.spanner; -import com.google.cloud.spanner.Database; -import com.google.cloud.spanner.DatabaseAdminClient; -import com.google.cloud.spanner.DatabaseId; -import com.google.cloud.spanner.Dialect; -import com.google.cloud.spanner.Spanner; -import com.google.cloud.spanner.SpannerException; -import com.google.common.collect.ImmutableList; -import jakarta.annotation.PostConstruct; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; @@ -36,36 +26,42 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; -import java.util.function.Consumer; -import org.apache.polaris.core.context.RealmContext; + import org.apache.polaris.core.persistence.bootstrap.SchemaOptions; -import org.apache.polaris.persistence.relational.spanner.model.Realm; import org.apache.polaris.persistence.relational.spanner.util.SpannerUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.Spanner; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; + @ApplicationScoped public class GoogleCloudSpannerDatabaseClientLifecycleManager { - private static Logger LOGGER = + private final static Logger LOGGER = LoggerFactory.getLogger(GoogleCloudSpannerDatabaseClientLifecycleManager.class); protected final GoogleCloudSpannerConfiguration spannerConfiguration; + protected final Spanner spanner; + protected final DatabaseId databaseId; public GoogleCloudSpannerDatabaseClientLifecycleManager( GoogleCloudSpannerConfiguration spannerConfiguration) { this.spannerConfiguration = spannerConfiguration; - } - - protected Spanner spanner; - protected DatabaseId databaseId; - - @PostConstruct - protected void init() { spanner = SpannerUtil.spannerFromConfiguration(spannerConfiguration); databaseId = SpannerUtil.databaseFromConfiguration(spannerConfiguration); + } + + + protected List getSpannerDatabaseDdl(SchemaOptions options) { final InputStream schemaStream; if (options.schemaFile() != null) { @@ -109,10 +105,9 @@ public SchemaInitializer getSchemaInitializer() { Database dbInfo = client.newDatabaseBuilder(databaseId).setDialect(Dialect.GOOGLE_STANDARD_SQL).build(); try { - spanner.getDatabaseAdminClient().updateDatabaseDdl(dbInfo, ddlStatements, null).get(); + client.updateDatabaseDdl(dbInfo, ddlStatements, null).get(); LOGGER.info("Successfully applied DDL update."); } catch (InterruptedException | ExecutionException e) { - LOGGER.error("Unable to update Spanner DDL.", e); throw new RuntimeException( "Unable to update Spanner DDL. Please disable this option for this database configuration.", e); @@ -120,19 +115,6 @@ public SchemaInitializer getSchemaInitializer() { }; } - @Produces - public Consumer getRealmInitializer() { - return (realmContext) -> { - try { - spanner - .getDatabaseClient(databaseId) - .write(ImmutableList.of(Realm.upsert(realmContext.getRealmIdentifier()))); - } catch (SpannerException e) { - LOGGER.error("Unable to initialize realm " + realmContext.getRealmIdentifier(), e); - } - }; - } - @Produces public DatabaseClientSupplier getDatabaseClientSupplier() { return () -> spanner.getDatabaseClient(databaseId); diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/RealmInitializer.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/RealmInitializer.java deleted file mode 100644 index 0e25a99073..0000000000 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/RealmInitializer.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -package org.apache.polaris.persistence.relational.spanner; - -import java.util.function.Consumer; -import org.apache.polaris.core.context.RealmContext; - -public interface RealmInitializer extends Consumer {} diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/model/Realm.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/model/Realm.java index ea5498c09a..0d1cd285ba 100644 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/model/Realm.java +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/model/Realm.java @@ -24,7 +24,7 @@ public final class Realm { - public static String TABLE_NAME = "Realms"; + public final static String TABLE_NAME = "Realms"; public static Mutation upsert(String realmId) { return Mutation.newInsertOrUpdateBuilder(TABLE_NAME).set("RealmId").to(realmId).build(); diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/Modifier.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/Modifier.java index 713d1ae5d7..86da2d9ac0 100644 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/Modifier.java +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/Modifier.java @@ -23,7 +23,7 @@ import java.util.function.BiFunction; import java.util.function.Function; -public class Modifier { +public final class Modifier { T wrapped; protected Modifier(T wrapped) { diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/SpannerUtil.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/SpannerUtil.java index 03cfd8b9eb..7caa065fc1 100644 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/SpannerUtil.java +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/SpannerUtil.java @@ -148,7 +148,6 @@ public StructReader next() { } public static Stream asStream(final ResultSet resultSet) { - return StreamSupport.stream( Spliterators.spliteratorUnknownSize(asIterator(resultSet), Spliterator.ORDERED), false); } From 191e14f39da90f789869f0545c775fbceaad9c4c Mon Sep 17 00:00:00 2001 From: Byron Ellis Date: Tue, 12 Aug 2025 17:45:59 -0700 Subject: [PATCH 6/8] spotless fix --- ...SpannerDatabaseClientLifecycleManager.java | 23 +++++++------------ .../relational/spanner/model/Realm.java | 2 +- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java index de3e2fe6f3..0a7db62fb9 100644 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java @@ -19,6 +19,13 @@ package org.apache.polaris.persistence.relational.spanner; +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.Spanner; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; @@ -26,25 +33,15 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; - import org.apache.polaris.core.persistence.bootstrap.SchemaOptions; import org.apache.polaris.persistence.relational.spanner.util.SpannerUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.cloud.spanner.Database; -import com.google.cloud.spanner.DatabaseAdminClient; -import com.google.cloud.spanner.DatabaseId; -import com.google.cloud.spanner.Dialect; -import com.google.cloud.spanner.Spanner; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; - @ApplicationScoped public class GoogleCloudSpannerDatabaseClientLifecycleManager { - private final static Logger LOGGER = + private static final Logger LOGGER = LoggerFactory.getLogger(GoogleCloudSpannerDatabaseClientLifecycleManager.class); protected final GoogleCloudSpannerConfiguration spannerConfiguration; @@ -56,12 +53,8 @@ public GoogleCloudSpannerDatabaseClientLifecycleManager( this.spannerConfiguration = spannerConfiguration; spanner = SpannerUtil.spannerFromConfiguration(spannerConfiguration); databaseId = SpannerUtil.databaseFromConfiguration(spannerConfiguration); - } - - - protected List getSpannerDatabaseDdl(SchemaOptions options) { final InputStream schemaStream; if (options.schemaFile() != null) { diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/model/Realm.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/model/Realm.java index 0d1cd285ba..17c08418ed 100644 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/model/Realm.java +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/model/Realm.java @@ -24,7 +24,7 @@ public final class Realm { - public final static String TABLE_NAME = "Realms"; + public static final String TABLE_NAME = "Realms"; public static Mutation upsert(String realmId) { return Mutation.newInsertOrUpdateBuilder(TABLE_NAME).set("RealmId").to(realmId).build(); From e04ca6a71511cfb1f79ac27f06d9e6e8e6d5b9db Mon Sep 17 00:00:00 2001 From: Byron Ellis Date: Thu, 14 Aug 2025 18:14:11 -0700 Subject: [PATCH 7/8] Change package name to get rid of relational since other packages were also refactored --- .../spanner/DatabaseAdminClientSupplier.java | 5 ++-- .../spanner/DatabaseClientSupplier.java | 5 ++-- .../GoogleCloudSpannerConfiguration.java | 5 ++-- ...SpannerDatabaseClientLifecycleManager.java | 24 +++++++++++-------- .../spanner/SchemaInitializer.java | 3 ++- .../{relational => }/spanner/model/Realm.java | 2 +- .../spanner/util/Modifier.java | 2 +- .../spanner/util/SpannerUtil.java | 5 ++-- 8 files changed, 30 insertions(+), 21 deletions(-) rename persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/{relational => }/spanner/DatabaseAdminClientSupplier.java (94%) rename persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/{relational => }/spanner/DatabaseClientSupplier.java (94%) rename persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/{relational => }/spanner/GoogleCloudSpannerConfiguration.java (95%) rename persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/{relational => }/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java (95%) rename persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/{relational => }/spanner/SchemaInitializer.java (94%) rename persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/{relational => }/spanner/model/Realm.java (94%) rename persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/{relational => }/spanner/util/Modifier.java (96%) rename persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/{relational => }/spanner/util/SpannerUtil.java (97%) diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/DatabaseAdminClientSupplier.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/DatabaseAdminClientSupplier.java similarity index 94% rename from persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/DatabaseAdminClientSupplier.java rename to persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/DatabaseAdminClientSupplier.java index fd578fa540..087613e593 100644 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/DatabaseAdminClientSupplier.java +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/DatabaseAdminClientSupplier.java @@ -17,9 +17,10 @@ * under the License. */ -package org.apache.polaris.persistence.relational.spanner; +package org.apache.polaris.persistence.spanner; -import com.google.cloud.spanner.DatabaseAdminClient; import java.util.function.Supplier; +import com.google.cloud.spanner.DatabaseAdminClient; + public interface DatabaseAdminClientSupplier extends Supplier {} diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/DatabaseClientSupplier.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/DatabaseClientSupplier.java similarity index 94% rename from persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/DatabaseClientSupplier.java rename to persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/DatabaseClientSupplier.java index 748a8b1ec5..e91aa94af9 100644 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/DatabaseClientSupplier.java +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/DatabaseClientSupplier.java @@ -17,9 +17,10 @@ * under the License. */ -package org.apache.polaris.persistence.relational.spanner; +package org.apache.polaris.persistence.spanner; -import com.google.cloud.spanner.DatabaseClient; import java.util.function.Supplier; +import com.google.cloud.spanner.DatabaseClient; + public interface DatabaseClientSupplier extends Supplier {} diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerConfiguration.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/GoogleCloudSpannerConfiguration.java similarity index 95% rename from persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerConfiguration.java rename to persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/GoogleCloudSpannerConfiguration.java index 1e220c32ed..f660f332a4 100644 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerConfiguration.java +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/GoogleCloudSpannerConfiguration.java @@ -17,11 +17,12 @@ * under the License. */ -package org.apache.polaris.persistence.relational.spanner; +package org.apache.polaris.persistence.spanner; -import io.smallrye.config.ConfigMapping; import java.util.Optional; +import io.smallrye.config.ConfigMapping; + @ConfigMapping(prefix = "polaris.persistence.spanner") public interface GoogleCloudSpannerConfiguration { diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java similarity index 95% rename from persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java rename to persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java index 0a7db62fb9..8dd020a84e 100644 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java @@ -17,15 +17,8 @@ * under the License. */ -package org.apache.polaris.persistence.relational.spanner; +package org.apache.polaris.persistence.spanner; -import com.google.cloud.spanner.Database; -import com.google.cloud.spanner.DatabaseAdminClient; -import com.google.cloud.spanner.DatabaseId; -import com.google.cloud.spanner.Dialect; -import com.google.cloud.spanner.Spanner; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; @@ -33,11 +26,21 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; + import org.apache.polaris.core.persistence.bootstrap.SchemaOptions; -import org.apache.polaris.persistence.relational.spanner.util.SpannerUtil; +import org.apache.polaris.persistence.spanner.util.SpannerUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.Spanner; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; + @ApplicationScoped public class GoogleCloudSpannerDatabaseClientLifecycleManager { @@ -76,7 +79,8 @@ protected List getSpannerDatabaseDdl(SchemaOptions options) { List lines = new ArrayList<>(); for (String s : schema.split("\n")) { s = s.trim(); - if (s.startsWith("--") || s.length() == 0) { + // Drop comments and empty lines. + if (s.startsWith("--") || s.length() == 0 || s.equals(";")) { continue; } lines.add(s); diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/SchemaInitializer.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/SchemaInitializer.java similarity index 94% rename from persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/SchemaInitializer.java rename to persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/SchemaInitializer.java index 494a0d1ea9..cdf70fd88d 100644 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/SchemaInitializer.java +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/SchemaInitializer.java @@ -17,9 +17,10 @@ * under the License. */ -package org.apache.polaris.persistence.relational.spanner; +package org.apache.polaris.persistence.spanner; import java.util.function.Consumer; + import org.apache.polaris.core.persistence.bootstrap.SchemaOptions; public interface SchemaInitializer extends Consumer {} diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/model/Realm.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/model/Realm.java similarity index 94% rename from persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/model/Realm.java rename to persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/model/Realm.java index 17c08418ed..2c7af6f72a 100644 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/model/Realm.java +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/model/Realm.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.polaris.persistence.relational.spanner.model; +package org.apache.polaris.persistence.spanner.model; import com.google.cloud.spanner.Key; import com.google.cloud.spanner.Mutation; diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/Modifier.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/util/Modifier.java similarity index 96% rename from persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/Modifier.java rename to persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/util/Modifier.java index 86da2d9ac0..9f875c10d5 100644 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/Modifier.java +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/util/Modifier.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.polaris.persistence.relational.spanner.util; +package org.apache.polaris.persistence.spanner.util; import java.util.Optional; import java.util.function.BiFunction; diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/SpannerUtil.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/util/SpannerUtil.java similarity index 97% rename from persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/SpannerUtil.java rename to persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/util/SpannerUtil.java index 7caa065fc1..09a6e38ca6 100644 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/relational/spanner/util/SpannerUtil.java +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/util/SpannerUtil.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.polaris.persistence.relational.spanner.util; +package org.apache.polaris.persistence.spanner.util; import com.google.cloud.ServiceOptions; import com.google.cloud.spanner.DatabaseId; @@ -42,7 +42,8 @@ import java.util.Spliterators; import java.util.stream.Stream; import java.util.stream.StreamSupport; -import org.apache.polaris.persistence.relational.spanner.GoogleCloudSpannerConfiguration; + +import org.apache.polaris.persistence.spanner.GoogleCloudSpannerConfiguration; public final class SpannerUtil { From 4c976ccf4614ecc1f48a84836d3f1fea062a220e Mon Sep 17 00:00:00 2001 From: Byron Ellis Date: Thu, 14 Aug 2025 18:15:50 -0700 Subject: [PATCH 8/8] spotless --- .../spanner/DatabaseAdminClientSupplier.java | 3 +-- .../spanner/DatabaseClientSupplier.java | 3 +-- .../GoogleCloudSpannerConfiguration.java | 3 +-- ...udSpannerDatabaseClientLifecycleManager.java | 17 +++++++---------- .../persistence/spanner/SchemaInitializer.java | 1 - .../persistence/spanner/util/SpannerUtil.java | 1 - 6 files changed, 10 insertions(+), 18 deletions(-) diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/DatabaseAdminClientSupplier.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/DatabaseAdminClientSupplier.java index 087613e593..559d460397 100644 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/DatabaseAdminClientSupplier.java +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/DatabaseAdminClientSupplier.java @@ -19,8 +19,7 @@ package org.apache.polaris.persistence.spanner; -import java.util.function.Supplier; - import com.google.cloud.spanner.DatabaseAdminClient; +import java.util.function.Supplier; public interface DatabaseAdminClientSupplier extends Supplier {} diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/DatabaseClientSupplier.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/DatabaseClientSupplier.java index e91aa94af9..9864b9123f 100644 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/DatabaseClientSupplier.java +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/DatabaseClientSupplier.java @@ -19,8 +19,7 @@ package org.apache.polaris.persistence.spanner; -import java.util.function.Supplier; - import com.google.cloud.spanner.DatabaseClient; +import java.util.function.Supplier; public interface DatabaseClientSupplier extends Supplier {} diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/GoogleCloudSpannerConfiguration.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/GoogleCloudSpannerConfiguration.java index f660f332a4..2d6883ba10 100644 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/GoogleCloudSpannerConfiguration.java +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/GoogleCloudSpannerConfiguration.java @@ -19,9 +19,8 @@ package org.apache.polaris.persistence.spanner; -import java.util.Optional; - import io.smallrye.config.ConfigMapping; +import java.util.Optional; @ConfigMapping(prefix = "polaris.persistence.spanner") public interface GoogleCloudSpannerConfiguration { diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java index 8dd020a84e..a9e6cea372 100644 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/GoogleCloudSpannerDatabaseClientLifecycleManager.java @@ -19,6 +19,13 @@ package org.apache.polaris.persistence.spanner; +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.Spanner; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; @@ -26,21 +33,11 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; - import org.apache.polaris.core.persistence.bootstrap.SchemaOptions; import org.apache.polaris.persistence.spanner.util.SpannerUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.cloud.spanner.Database; -import com.google.cloud.spanner.DatabaseAdminClient; -import com.google.cloud.spanner.DatabaseId; -import com.google.cloud.spanner.Dialect; -import com.google.cloud.spanner.Spanner; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; - @ApplicationScoped public class GoogleCloudSpannerDatabaseClientLifecycleManager { diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/SchemaInitializer.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/SchemaInitializer.java index cdf70fd88d..eb818268bc 100644 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/SchemaInitializer.java +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/SchemaInitializer.java @@ -20,7 +20,6 @@ package org.apache.polaris.persistence.spanner; import java.util.function.Consumer; - import org.apache.polaris.core.persistence.bootstrap.SchemaOptions; public interface SchemaInitializer extends Consumer {} diff --git a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/util/SpannerUtil.java b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/util/SpannerUtil.java index 09a6e38ca6..ee9786a0fa 100644 --- a/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/util/SpannerUtil.java +++ b/persistence/google-cloud-spanner/src/main/java/org/apache/polaris/persistence/spanner/util/SpannerUtil.java @@ -42,7 +42,6 @@ import java.util.Spliterators; import java.util.stream.Stream; import java.util.stream.StreamSupport; - import org.apache.polaris.persistence.spanner.GoogleCloudSpannerConfiguration; public final class SpannerUtil {