Skip to content

Commit 0741431

Browse files
committed
Rebases Byron's PR agaist latest main
1 parent 81f4c08 commit 0741431

File tree

15 files changed

+619
-6
lines changed

15 files changed

+619
-6
lines changed

gradle/libs.versions.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ cel-bom = { module = "org.projectnessie.cel:cel-bom", version = "0.5.3" }
5252
commons-lang3 = { module = "org.apache.commons:commons-lang3", version = "3.20.0" }
5353
commons-text = { module = "org.apache.commons:commons-text", version = "1.15.0" }
5454
errorprone = { module = "com.google.errorprone:error_prone_core", version = "2.45.0" }
55-
google-cloud-iamcredentials = { module = "com.google.cloud:google-cloud-iamcredentials", version = "2.80.0" }
56-
google-cloud-storage-bom = { module = "com.google.cloud:google-cloud-storage-bom", version = "2.60.0" }
55+
56+
google-cloud-libraries-bom = { module = "com.google.cloud:libraries-bom", version = "26.72.0" }
5757
guava = { module = "com.google.guava:guava", version = "33.5.0-jre" }
5858
h2 = { module = "com.h2database:h2", version = "2.4.240" }
5959
dnsjava = { module = "dnsjava:dnsjava", version = "3.6.3" }

gradle/projects.main.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ polaris-admin=runtime/admin
3333
polaris-runtime-common=runtime/common
3434
polaris-runtime-test-common=runtime/test-common
3535
polaris-relational-jdbc=persistence/relational-jdbc
36+
polaris-google-cloud-spanner=persistence/google-cloud-spanner
3637
polaris-tests=integration-tests
3738
aggregated-license-report=aggregated-license-report
3839
polaris-immutables=tools/immutables
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
plugins {
21+
id("polaris-server")
22+
id("org.kordamp.gradle.jandex")
23+
}
24+
25+
dependencies {
26+
implementation(project(":polaris-core"))
27+
implementation(libs.slf4j.api)
28+
implementation(libs.guava)
29+
30+
implementation(platform(libs.google.cloud.libraries.bom))
31+
implementation("com.google.cloud:google-cloud-spanner")
32+
33+
compileOnly(libs.jakarta.annotation.api)
34+
compileOnly(libs.jakarta.enterprise.cdi.api)
35+
compileOnly(libs.jakarta.inject.api)
36+
37+
compileOnly(libs.smallrye.common.annotation) // @Identifier
38+
compileOnly(libs.smallrye.config.core) // @ConfigMapping
39+
40+
testImplementation(libs.mockito.junit.jupiter)
41+
testImplementation(libs.h2)
42+
testImplementation(testFixtures(project(":polaris-core")))
43+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.polaris.persistence.spanner;
21+
22+
import com.google.cloud.spanner.DatabaseAdminClient;
23+
import java.util.function.Supplier;
24+
25+
public interface DatabaseAdminClientSupplier extends Supplier<DatabaseAdminClient> {}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.polaris.persistence.spanner;
21+
22+
import com.google.cloud.spanner.DatabaseClient;
23+
import java.util.function.Supplier;
24+
25+
public interface DatabaseClientSupplier extends Supplier<DatabaseClient> {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.polaris.persistence.spanner;
21+
22+
import io.smallrye.config.ConfigMapping;
23+
import java.util.Optional;
24+
25+
@ConfigMapping(prefix = "polaris.persistence.spanner")
26+
public interface GoogleCloudSpannerConfiguration {
27+
28+
public Optional<String> quotaProjectId();
29+
30+
public Optional<String> projectId();
31+
32+
public Optional<String> instanceId();
33+
34+
public Optional<String> databaseId();
35+
36+
public Optional<String> emulatorHost();
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.polaris.persistence.spanner;
21+
22+
import com.google.cloud.spanner.Database;
23+
import com.google.cloud.spanner.DatabaseAdminClient;
24+
import com.google.cloud.spanner.DatabaseId;
25+
import com.google.cloud.spanner.Dialect;
26+
import com.google.cloud.spanner.Spanner;
27+
import jakarta.enterprise.context.ApplicationScoped;
28+
import jakarta.enterprise.inject.Produces;
29+
import java.io.FileInputStream;
30+
import java.io.IOException;
31+
import java.io.InputStream;
32+
import java.nio.charset.Charset;
33+
import java.util.ArrayList;
34+
import java.util.List;
35+
import java.util.concurrent.ExecutionException;
36+
import org.apache.polaris.core.persistence.bootstrap.SchemaOptions;
37+
import org.apache.polaris.persistence.spanner.util.SpannerUtil;
38+
import org.slf4j.Logger;
39+
import org.slf4j.LoggerFactory;
40+
41+
@ApplicationScoped
42+
public class GoogleCloudSpannerDatabaseClientLifecycleManager {
43+
44+
private static final Logger LOGGER =
45+
LoggerFactory.getLogger(GoogleCloudSpannerDatabaseClientLifecycleManager.class);
46+
47+
protected final GoogleCloudSpannerConfiguration spannerConfiguration;
48+
protected final Spanner spanner;
49+
protected final DatabaseId databaseId;
50+
51+
public GoogleCloudSpannerDatabaseClientLifecycleManager(
52+
GoogleCloudSpannerConfiguration spannerConfiguration) {
53+
this.spannerConfiguration = spannerConfiguration;
54+
spanner = SpannerUtil.spannerFromConfiguration(spannerConfiguration);
55+
databaseId = SpannerUtil.databaseFromConfiguration(spannerConfiguration);
56+
}
57+
58+
protected List<String> getSpannerDatabaseDdl(SchemaOptions options) {
59+
final InputStream schemaStream;
60+
if (options.schemaFile().isPresent()) {
61+
try {
62+
schemaStream = new FileInputStream(options.schemaFile().get());
63+
} catch (IOException e) {
64+
throw new IllegalArgumentException("Unable to load file " + options.schemaFile().get(), e);
65+
}
66+
} else {
67+
int version = options.schemaVersion().orElse(1);
68+
if (version == 1) {
69+
schemaStream =
70+
getClass().getResourceAsStream("/org/apache/polaris/persistence/spanner/schema-v1.sql");
71+
} else {
72+
throw new IllegalArgumentException("Unknown schema version " + version);
73+
}
74+
}
75+
try (schemaStream) {
76+
String schema = new String(schemaStream.readAllBytes(), Charset.forName("UTF-8"));
77+
List<String> lines = new ArrayList<>();
78+
for (String s : schema.split("\n")) {
79+
s = s.trim();
80+
// Drop comments and empty lines.
81+
if (s.startsWith("--") || s.length() == 0 || s.equals(";")) {
82+
continue;
83+
}
84+
lines.add(s);
85+
}
86+
return List.of(String.join(" ", lines).split(";"));
87+
} catch (IOException e) {
88+
throw new RuntimeException("Unable to retrieve DDL statements", e);
89+
}
90+
}
91+
92+
@Produces
93+
public SchemaInitializer getSchemaInitializer() {
94+
return (options) -> {
95+
List<String> ddlStatements = getSpannerDatabaseDdl(options);
96+
LOGGER.info(
97+
"Attempting to initialize Spanner database DDL with {} statements,",
98+
ddlStatements.size());
99+
DatabaseAdminClient client = spanner.getDatabaseAdminClient();
100+
Database dbInfo =
101+
client.newDatabaseBuilder(databaseId).setDialect(Dialect.GOOGLE_STANDARD_SQL).build();
102+
try {
103+
client.updateDatabaseDdl(dbInfo, ddlStatements, null).get();
104+
LOGGER.info("Successfully applied DDL update.");
105+
} catch (InterruptedException | ExecutionException e) {
106+
throw new RuntimeException(
107+
"Unable to update Spanner DDL. Please disable this option for this database configuration.",
108+
e);
109+
}
110+
};
111+
}
112+
113+
@Produces
114+
public DatabaseClientSupplier getDatabaseClientSupplier() {
115+
return () -> spanner.getDatabaseClient(databaseId);
116+
}
117+
118+
@Produces
119+
public DatabaseAdminClientSupplier getDatabaseAdminClientSupplier() {
120+
return () -> spanner.getDatabaseAdminClient();
121+
}
122+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.polaris.persistence.spanner;
21+
22+
import java.util.function.Consumer;
23+
import org.apache.polaris.core.persistence.bootstrap.SchemaOptions;
24+
25+
public interface SchemaInitializer extends Consumer<SchemaOptions> {}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.polaris.persistence.spanner.model;
21+
22+
import com.google.cloud.spanner.Key;
23+
import com.google.cloud.spanner.Mutation;
24+
25+
public final class Realm {
26+
27+
public static final String TABLE_NAME = "Realms";
28+
29+
public static Mutation upsert(String realmId) {
30+
return Mutation.newInsertOrUpdateBuilder(TABLE_NAME).set("RealmId").to(realmId).build();
31+
}
32+
33+
public static Mutation delete(String realmId) {
34+
return Mutation.delete(TABLE_NAME, Key.of(realmId));
35+
}
36+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.polaris.persistence.spanner.util;
21+
22+
import java.util.Optional;
23+
import java.util.function.BiFunction;
24+
import java.util.function.Function;
25+
26+
public final class Modifier<T> {
27+
T wrapped;
28+
29+
protected Modifier(T wrapped) {
30+
this.wrapped = wrapped;
31+
}
32+
33+
public Modifier<T> apply(Function<T, T> fn) {
34+
wrapped = fn.apply(wrapped);
35+
return this;
36+
}
37+
38+
public <V> Modifier<T> orElse(Optional<V> toApply, V other, BiFunction<T, V, T> fn) {
39+
wrapped = fn.apply(wrapped, toApply.orElse(other));
40+
return this;
41+
}
42+
43+
public <V> Modifier<T> ifPresent(Optional<V> toApply, BiFunction<T, V, T> fn) {
44+
if (toApply.isPresent()) {
45+
wrapped = fn.apply(wrapped, toApply.get());
46+
}
47+
return this;
48+
}
49+
50+
public T get() {
51+
return wrapped;
52+
}
53+
54+
public static <T> Modifier<T> of(T value) {
55+
return new Modifier<>(value);
56+
}
57+
}

0 commit comments

Comments
 (0)