Skip to content

Commit 0fb6076

Browse files
authored
[core] Support alter database (apache#4700)
1 parent 659cf39 commit 0fb6076

File tree

37 files changed

+1049
-55
lines changed

37 files changed

+1049
-55
lines changed

docs/content/flink/sql-alter.md

+16
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,19 @@ The following SQL modifies the watermark strategy to `ts - INTERVAL '2' HOUR`.
227227
```sql
228228
ALTER TABLE my_table MODIFY WATERMARK FOR ts AS ts - INTERVAL '2' HOUR
229229
```
230+
231+
# ALTER DATABASE
232+
233+
The following SQL sets one or more properties in the specified database. If a particular property is already set in the database, override the old value with the new one.
234+
235+
```sql
236+
ALTER DATABASE [catalog_name.]db_name SET (key1=val1, key2=val2, ...)
237+
```
238+
239+
## Altering Database Location
240+
241+
The following SQL changes location of database `my_database` to `file:/temp/my_database`.
242+
243+
```sql
244+
ALTER DATABASE my_database SET ('location' = 'file:/temp/my_database')
245+
```

docs/content/program-api/catalog-api.md

+25-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public class ListDatabases {
8282

8383
## Drop Database
8484

85-
You can use the catalog to drop databases.
85+
You can use the catalog to drop database.
8686

8787
```java
8888
import org.apache.paimon.catalog.Catalog;
@@ -102,6 +102,30 @@ public class DropDatabase {
102102
}
103103
```
104104

105+
## Alter Database
106+
107+
You can use the catalog to alter database's properties.(ps: only support hive and jdbc catalog)
108+
109+
```java
110+
import java.util.ArrayList;
111+
import org.apache.paimon.catalog.Catalog;
112+
113+
public class AlterDatabase {
114+
115+
public static void main(String[] args) {
116+
try {
117+
Catalog catalog = CreateCatalog.createHiveCatalog();
118+
List<DatabaseChange> changes = new ArrayList<>();
119+
changes.add(DatabaseChange.setProperty("k1", "v1"));
120+
changes.add(DatabaseChange.removeProperty("k2"));
121+
catalog.alterDatabase("my_db", changes, true);
122+
} catch (Catalog.DatabaseNotExistException e) {
123+
// do something
124+
}
125+
}
126+
}
127+
```
128+
105129
## Determine Whether Table Exists
106130

107131
You can use the catalog to determine whether the table exists

docs/content/spark/sql-alter.md

+18
Original file line numberDiff line numberDiff line change
@@ -240,3 +240,21 @@ The following SQL changes the type of a nested column `f2` to `BIGINT` in a stru
240240
-- column v previously has type MAP<INT, STRUCT<f1: STRING, f2: INT>>
241241
ALTER TABLE my_table ALTER COLUMN v.value.f2 TYPE BIGINT;
242242
```
243+
244+
245+
# ALTER DATABASE
246+
247+
The following SQL sets one or more properties in the specified database. If a particular property is already set in the database, override the old value with the new one.
248+
249+
```sql
250+
ALTER { DATABASE | SCHEMA | NAMESPACE } my_database
251+
SET { DBPROPERTIES | PROPERTIES } ( property_name = property_value [ , ... ] )
252+
```
253+
254+
## Altering Database Location
255+
256+
The following SQL sets the location of the specified database to `file:/temp/my_database.db`.
257+
258+
```sql
259+
ALTER DATABASE my_database SET LOCATION 'file:/temp/my_database.db'
260+
```

paimon-core/src/main/java/org/apache/paimon/catalog/AbstractCatalog.java

+20
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,26 @@ public void dropDatabase(String name, boolean ignoreIfNotExists, boolean cascade
223223

224224
protected abstract void dropDatabaseImpl(String name);
225225

226+
@Override
227+
public void alterDatabase(String name, List<PropertyChange> changes, boolean ignoreIfNotExists)
228+
throws DatabaseNotExistException {
229+
checkNotSystemDatabase(name);
230+
try {
231+
if (changes == null || changes.isEmpty()) {
232+
return;
233+
}
234+
alterDatabaseImpl(name, changes);
235+
} catch (DatabaseNotExistException e) {
236+
if (ignoreIfNotExists) {
237+
return;
238+
}
239+
throw new DatabaseNotExistException(name);
240+
}
241+
}
242+
243+
protected abstract void alterDatabaseImpl(String name, List<PropertyChange> changes)
244+
throws DatabaseNotExistException;
245+
226246
@Override
227247
public List<String> listTables(String databaseName) throws DatabaseNotExistException {
228248
if (isSystemDatabase(databaseName)) {

paimon-core/src/main/java/org/apache/paimon/catalog/CachingCatalog.java

+7
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,13 @@ public void dropDatabase(String name, boolean ignoreIfNotExists, boolean cascade
187187
}
188188
}
189189

190+
@Override
191+
public void alterDatabase(String name, List<PropertyChange> changes, boolean ignoreIfNotExists)
192+
throws DatabaseNotExistException {
193+
super.alterDatabase(name, changes, ignoreIfNotExists);
194+
databaseCache.invalidate(name);
195+
}
196+
190197
@Override
191198
public void dropTable(Identifier identifier, boolean ignoreIfNotExists)
192199
throws TableNotExistException {

paimon-core/src/main/java/org/apache/paimon/catalog/Catalog.java

+13
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,19 @@ void createDatabase(String name, boolean ignoreIfExists, Map<String, String> pro
126126
void dropDatabase(String name, boolean ignoreIfNotExists, boolean cascade)
127127
throws DatabaseNotExistException, DatabaseNotEmptyException;
128128

129+
/**
130+
* Alter a database.
131+
*
132+
* @param name Name of the database to alter.
133+
* @param changes the property changes
134+
* @param ignoreIfNotExists Flag to specify behavior when the database does not exist: if set to
135+
* false, throw an exception, if set to true, do nothing.
136+
* @throws DatabaseNotExistException if the given database is not exist and ignoreIfNotExists is
137+
* false
138+
*/
139+
void alterDatabase(String name, List<PropertyChange> changes, boolean ignoreIfNotExists)
140+
throws DatabaseNotExistException;
141+
129142
/**
130143
* Return a {@link Table} identified by the given {@link Identifier}.
131144
*

paimon-core/src/main/java/org/apache/paimon/catalog/DelegateCatalog.java

+6
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ public void dropDatabase(String name, boolean ignoreIfNotExists, boolean cascade
8383
wrapped.dropDatabase(name, ignoreIfNotExists, cascade);
8484
}
8585

86+
@Override
87+
public void alterDatabase(String name, List<PropertyChange> changes, boolean ignoreIfNotExists)
88+
throws DatabaseNotExistException {
89+
wrapped.alterDatabase(name, changes, ignoreIfNotExists);
90+
}
91+
8692
@Override
8793
public List<String> listTables(String databaseName) throws DatabaseNotExistException {
8894
return wrapped.listTables(databaseName);

paimon-core/src/main/java/org/apache/paimon/catalog/FileSystemCatalog.java

+5
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ protected void dropDatabaseImpl(String name) {
9292
uncheck(() -> fileIO.delete(newDatabasePath(name), true));
9393
}
9494

95+
@Override
96+
protected void alterDatabaseImpl(String name, List<PropertyChange> changes) {
97+
throw new UnsupportedOperationException("Alter database is not supported.");
98+
}
99+
95100
@Override
96101
protected List<String> listTablesImpl(String databaseName) {
97102
return uncheck(() -> listTablesInFileSystem(newDatabasePath(databaseName)));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
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, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.paimon.catalog;
20+
21+
import org.apache.paimon.utils.Pair;
22+
23+
import org.apache.paimon.shade.guava30.com.google.common.collect.Maps;
24+
import org.apache.paimon.shade.guava30.com.google.common.collect.Sets;
25+
26+
import java.util.List;
27+
import java.util.Map;
28+
import java.util.Set;
29+
30+
/** define change to the database property. */
31+
public interface PropertyChange {
32+
33+
static PropertyChange setProperty(String property, String value) {
34+
return new SetProperty(property, value);
35+
}
36+
37+
static PropertyChange removeProperty(String property) {
38+
return new RemoveProperty(property);
39+
}
40+
41+
static Pair<Map<String, String>, Set<String>> getSetPropertiesToRemoveKeys(
42+
List<PropertyChange> changes) {
43+
Map<String, String> setProperties = Maps.newHashMap();
44+
Set<String> removeKeys = Sets.newHashSet();
45+
changes.forEach(
46+
change -> {
47+
if (change instanceof PropertyChange.SetProperty) {
48+
PropertyChange.SetProperty setProperty =
49+
(PropertyChange.SetProperty) change;
50+
setProperties.put(setProperty.property(), setProperty.value());
51+
} else {
52+
removeKeys.add(((PropertyChange.RemoveProperty) change).property());
53+
}
54+
});
55+
return Pair.of(setProperties, removeKeys);
56+
}
57+
58+
/** Set property for database change. */
59+
final class SetProperty implements PropertyChange {
60+
61+
private final String property;
62+
private final String value;
63+
64+
private SetProperty(String property, String value) {
65+
this.property = property;
66+
this.value = value;
67+
}
68+
69+
public String property() {
70+
return this.property;
71+
}
72+
73+
public String value() {
74+
return this.value;
75+
}
76+
}
77+
78+
/** Remove property for database change. */
79+
final class RemoveProperty implements PropertyChange {
80+
81+
private final String property;
82+
83+
private RemoveProperty(String property) {
84+
this.property = property;
85+
}
86+
87+
public String property() {
88+
return this.property;
89+
}
90+
}
91+
}

paimon-core/src/main/java/org/apache/paimon/jdbc/JdbcCatalog.java

+45
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.apache.paimon.catalog.CatalogLockFactory;
2525
import org.apache.paimon.catalog.Database;
2626
import org.apache.paimon.catalog.Identifier;
27+
import org.apache.paimon.catalog.PropertyChange;
2728
import org.apache.paimon.fs.FileIO;
2829
import org.apache.paimon.fs.Path;
2930
import org.apache.paimon.operation.Lock;
@@ -33,11 +34,13 @@
3334
import org.apache.paimon.schema.SchemaChange;
3435
import org.apache.paimon.schema.SchemaManager;
3536
import org.apache.paimon.schema.TableSchema;
37+
import org.apache.paimon.utils.Pair;
3638
import org.apache.paimon.utils.Preconditions;
3739

3840
import org.apache.paimon.shade.guava30.com.google.common.collect.ImmutableMap;
3941
import org.apache.paimon.shade.guava30.com.google.common.collect.Lists;
4042
import org.apache.paimon.shade.guava30.com.google.common.collect.Maps;
43+
import org.apache.paimon.shade.guava30.com.google.common.collect.Sets;
4144

4245
import org.slf4j.Logger;
4346
import org.slf4j.LoggerFactory;
@@ -52,12 +55,15 @@
5255
import java.util.List;
5356
import java.util.Map;
5457
import java.util.Optional;
58+
import java.util.Set;
5559
import java.util.stream.Collectors;
5660

5761
import static org.apache.paimon.jdbc.JdbcCatalogLock.acquireTimeout;
5862
import static org.apache.paimon.jdbc.JdbcCatalogLock.checkMaxSleep;
63+
import static org.apache.paimon.jdbc.JdbcUtils.deleteProperties;
5964
import static org.apache.paimon.jdbc.JdbcUtils.execute;
6065
import static org.apache.paimon.jdbc.JdbcUtils.insertProperties;
66+
import static org.apache.paimon.jdbc.JdbcUtils.updateProperties;
6167
import static org.apache.paimon.jdbc.JdbcUtils.updateTable;
6268

6369
/* This file is based on source code from the Iceberg Project (http://iceberg.apache.org/), licensed by the Apache
@@ -197,6 +203,45 @@ protected void dropDatabaseImpl(String name) {
197203
execute(connections, JdbcUtils.DELETE_ALL_DATABASE_PROPERTIES_SQL, catalogKey, name);
198204
}
199205

206+
@Override
207+
protected void alterDatabaseImpl(String name, List<PropertyChange> changes) {
208+
Pair<Map<String, String>, Set<String>> setPropertiesToRemoveKeys =
209+
PropertyChange.getSetPropertiesToRemoveKeys(changes);
210+
Map<String, String> setProperties = setPropertiesToRemoveKeys.getLeft();
211+
Set<String> removeKeys = setPropertiesToRemoveKeys.getRight();
212+
Map<String, String> startingProperties = fetchProperties(name);
213+
Map<String, String> inserts = Maps.newHashMap();
214+
Map<String, String> updates = Maps.newHashMap();
215+
Set<String> removes = Sets.newHashSet();
216+
if (!setProperties.isEmpty()) {
217+
setProperties.forEach(
218+
(k, v) -> {
219+
if (!startingProperties.containsKey(k)) {
220+
inserts.put(k, v);
221+
} else {
222+
updates.put(k, v);
223+
}
224+
});
225+
}
226+
if (!removeKeys.isEmpty()) {
227+
removeKeys.forEach(
228+
k -> {
229+
if (startingProperties.containsKey(k)) {
230+
removes.add(k);
231+
}
232+
});
233+
}
234+
if (!inserts.isEmpty()) {
235+
insertProperties(connections, catalogKey, name, inserts);
236+
}
237+
if (!updates.isEmpty()) {
238+
updateProperties(connections, catalogKey, name, updates);
239+
}
240+
if (!removes.isEmpty()) {
241+
deleteProperties(connections, catalogKey, name, removes);
242+
}
243+
}
244+
200245
@Override
201246
protected List<String> listTablesImpl(String databaseName) {
202247
return fetch(

0 commit comments

Comments
 (0)