Skip to content

Commit 51c4af1

Browse files
committed
[server] Forbid any table/partition creation that begins with __
1 parent 97d6f34 commit 51c4af1

File tree

5 files changed

+54
-15
lines changed

5 files changed

+54
-15
lines changed

fluss-common/src/main/java/org/apache/fluss/metadata/TablePath.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ public class TablePath implements Serializable {
5454
// RecordAccumulator.ready)
5555
private Integer hash;
5656

57+
private static final String INTERNAL_NAME_PREFIX = "__";
58+
5759
public TablePath(String databaseName, String tableName) {
5860
this.databaseName = databaseName;
5961
this.tableName = tableName;
@@ -127,20 +129,35 @@ public String toString() {
127129

128130
public static void validateDatabaseName(String databaseName) throws InvalidDatabaseException {
129131
String dbError = detectInvalidName(databaseName);
130-
if (dbError != null) {
132+
String dbInternalNameError = validatePrefix(databaseName);
133+
if (dbError != null || dbInternalNameError != null) {
131134
throw new InvalidDatabaseException(
132-
"Database name " + databaseName + " is invalid: " + dbError);
135+
"Database name "
136+
+ databaseName
137+
+ " is invalid: "
138+
+ (dbError != null ? dbError : dbInternalNameError));
133139
}
134140
}
135141

136142
public static void validateTableName(String tableName) throws InvalidTableException {
137143
String tableError = detectInvalidName(tableName);
138-
if (tableError != null) {
144+
String tableInternalNameError = validatePrefix(tableName);
145+
if (tableError != null || tableInternalNameError != null) {
139146
throw new InvalidTableException(
140-
"Table name " + tableName + " is invalid: " + tableError);
147+
"Table name "
148+
+ tableName
149+
+ " is invalid: "
150+
+ (tableError != null ? tableError : tableInternalNameError));
141151
}
142152
}
143153

154+
public static String validatePrefix(String identifier) throws InvalidTableException {
155+
if (identifier != null && identifier.startsWith(INTERNAL_NAME_PREFIX)) {
156+
return "'" + INTERNAL_NAME_PREFIX + "' is not allowed as prefix";
157+
}
158+
return null;
159+
}
160+
144161
public static String detectInvalidName(String identifier) {
145162
if (identifier == null) {
146163
return "null string is not allowed";

fluss-common/src/main/java/org/apache/fluss/utils/PartitionUtils.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import java.util.Map;
3838

3939
import static org.apache.fluss.metadata.TablePath.detectInvalidName;
40+
import static org.apache.fluss.metadata.TablePath.validatePrefix;
4041

4142
/** Utils for partition. */
4243
public class PartitionUtils {
@@ -66,7 +67,10 @@ public class PartitionUtils {
6667
private static final String HOUR_FORMAT = "yyyyMMddHH";
6768

6869
public static void validatePartitionSpec(
69-
TablePath tablePath, List<String> partitionKeys, PartitionSpec partitionSpec) {
70+
TablePath tablePath,
71+
List<String> partitionKeys,
72+
PartitionSpec partitionSpec,
73+
boolean isCreate) {
7074
Map<String, String> partitionSpecMap = partitionSpec.getSpecMap();
7175
if (partitionKeys.size() != partitionSpecMap.size()) {
7276
throw new InvalidPartitionException(
@@ -87,16 +91,21 @@ public static void validatePartitionSpec(
8791
}
8892
}
8993

90-
validatePartitionValues(reOrderedPartitionValues);
94+
validatePartitionValues(reOrderedPartitionValues, isCreate);
9195
}
9296

9397
@VisibleForTesting
94-
static void validatePartitionValues(List<String> partitionValues) {
98+
static void validatePartitionValues(List<String> partitionValues, boolean isCreate) {
9599
for (String value : partitionValues) {
96-
String invalidName = detectInvalidName(value);
97-
if (invalidName != null) {
100+
String invalidNameError = detectInvalidName(value);
101+
if (invalidNameError != null || (isCreate && validatePrefix(value) != null)) {
98102
throw new InvalidPartitionException(
99-
"The partition value " + value + " is invalid: " + invalidName);
103+
"The partition value "
104+
+ value
105+
+ " is invalid: "
106+
+ (invalidNameError != null
107+
? invalidNameError
108+
: validatePrefix(value)));
100109
}
101110
}
102111
}

fluss-common/src/test/java/org/apache/fluss/metadata/TablePathTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ void testValidate() {
3737
assertThat(path.isValid()).isTrue();
3838
assertThat(path.toString()).isEqualTo("db_2-abc3.table-1_abc_2");
3939

40+
// assert invalid name prefix
41+
TablePath invalidPath = TablePath.of("db_2", "__table-1");
42+
assertThatThrownBy(invalidPath::validate)
43+
.isInstanceOf(InvalidTableException.class)
44+
.hasMessageContaining(
45+
"Table name __table-1 is invalid: '__' is not allowed as prefix");
46+
4047
// check max length
4148
String longName = StringUtils.repeat("a", 200);
4249
assertThat(TablePath.of(longName, longName).isValid()).isTrue();

fluss-common/src/test/java/org/apache/fluss/utils/PartitionUtilsTest.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,18 +52,23 @@ class PartitionUtilsTest {
5252

5353
@Test
5454
void testValidatePartitionValues() {
55-
assertThatThrownBy(() -> validatePartitionValues(Arrays.asList("$1", "2")))
55+
assertThatThrownBy(() -> validatePartitionValues(Arrays.asList("$1", "2"), true))
5656
.isInstanceOf(InvalidPartitionException.class)
5757
.hasMessageContaining(
5858
"The partition value $1 is invalid: '$1' contains one "
5959
+ "or more characters other than ASCII alphanumerics, '_' and '-'");
6060

61-
assertThatThrownBy(() -> validatePartitionValues(Arrays.asList("?1", "2")))
61+
assertThatThrownBy(() -> validatePartitionValues(Arrays.asList("?1", "2"), true))
6262
.isInstanceOf(InvalidPartitionException.class)
6363
.hasMessageContaining(
6464
"The partition value ?1 is invalid: '?1' contains one or more "
6565
+ "characters other than ASCII alphanumerics, '_' and '-'");
6666

67+
assertThatThrownBy(() -> validatePartitionValues(Arrays.asList("__p1", "2"), true))
68+
.isInstanceOf(InvalidPartitionException.class)
69+
.hasMessageContaining(
70+
"The partition value __p1 is invalid: '__' is not allowed as prefix");
71+
6772
TableDescriptor descriptor =
6873
TableDescriptor.builder()
6974
.schema(DATA1_SCHEMA)
@@ -80,7 +85,8 @@ void testValidatePartitionValues() {
8085
validatePartitionSpec(
8186
tableInfo.getTablePath(),
8287
tableInfo.getPartitionKeys(),
83-
new PartitionSpec(Collections.emptyMap())))
88+
new PartitionSpec(Collections.emptyMap()),
89+
true))
8490
.isInstanceOf(InvalidPartitionException.class)
8591
.hasMessageContaining(
8692
"PartitionSpec size is not equal to partition keys size for "

fluss-server/src/main/java/org/apache/fluss/server/coordinator/CoordinatorService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ public CompletableFuture<CreatePartitionResponse> createPartition(
376376

377377
// first, validate the partition spec, and get resolved partition spec.
378378
PartitionSpec partitionSpec = getPartitionSpec(request.getPartitionSpec());
379-
validatePartitionSpec(tablePath, table.partitionKeys, partitionSpec);
379+
validatePartitionSpec(tablePath, table.partitionKeys, partitionSpec, true);
380380
ResolvedPartitionSpec partitionToCreate =
381381
ResolvedPartitionSpec.fromPartitionSpec(table.partitionKeys, partitionSpec);
382382

@@ -417,7 +417,7 @@ public CompletableFuture<DropPartitionResponse> dropPartition(DropPartitionReque
417417

418418
// first, validate the partition spec.
419419
PartitionSpec partitionSpec = getPartitionSpec(request.getPartitionSpec());
420-
validatePartitionSpec(tablePath, table.partitionKeys, partitionSpec);
420+
validatePartitionSpec(tablePath, table.partitionKeys, partitionSpec, false);
421421
ResolvedPartitionSpec partitionToDrop =
422422
ResolvedPartitionSpec.fromPartitionSpec(table.partitionKeys, partitionSpec);
423423

0 commit comments

Comments
 (0)