Skip to content

Commit 55eb34e

Browse files
committed
modified based on CR
1 parent e4b5232 commit 55eb34e

File tree

14 files changed

+285
-382
lines changed

14 files changed

+285
-382
lines changed

fluss-client/src/test/java/org/apache/fluss/client/admin/FlussAdminITCase.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
import org.apache.fluss.server.kv.snapshot.KvSnapshotHandle;
7272
import org.apache.fluss.server.zk.ZooKeeperClient;
7373
import org.apache.fluss.server.zk.data.ServerTags;
74+
import org.apache.fluss.types.DataTypeEqualsWithFieldId;
7475
import org.apache.fluss.types.DataTypes;
7576

7677
import org.junit.jupiter.api.BeforeEach;
@@ -430,6 +431,11 @@ void testAlterTableColumn() throws Exception {
430431
.build();
431432
SchemaInfo schemaInfo = admin.getTableSchema(tablePath).get();
432433
assertThat(schemaInfo).isEqualTo(new SchemaInfo(expectedSchema, 2));
434+
// test field_id of rowType
435+
assertThat(
436+
DataTypeEqualsWithFieldId.equals(
437+
schemaInfo.getSchema().getRowType(), expectedSchema.getRowType()))
438+
.isTrue();
433439
}
434440

435441
@Test

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -815,9 +815,10 @@ private static void checkFieldIds(List<Column> columns, int highestFieldId) {
815815
Integer maximumFieldId = allFieldIds.stream().max(Integer::compareTo).orElse(-1);
816816
checkState(
817817
columns.isEmpty() || highestFieldId >= maximumFieldId,
818-
"Highest field ID (%s) must be greater than or equal to the maximum field ID (%s) including nested fields.",
818+
"Highest field ID (%s) must be greater than or equal to the maximum field ID (%s) including nested fields. Current columns is %s",
819819
highestFieldId,
820-
maximumFieldId);
820+
maximumFieldId,
821+
columns);
821822
}
822823

823824
/**

fluss-common/src/main/java/org/apache/fluss/types/RowType.java

Lines changed: 21 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import java.util.List;
2626
import java.util.Objects;
2727
import java.util.Set;
28-
import java.util.concurrent.atomic.AtomicInteger;
2928
import java.util.stream.Collectors;
3029

3130
import static org.apache.fluss.utils.Preconditions.checkNotNull;
@@ -51,7 +50,9 @@ public RowType(boolean isNullable, List<DataField> fields) {
5150
super(isNullable, DataTypeRoot.ROW);
5251
this.fields =
5352
Collections.unmodifiableList(
54-
validateFields(checkNotNull(fields, "Fields must not be null.")));
53+
new ArrayList<>(checkNotNull(fields, "Fields must not be null.")));
54+
55+
validateFields(fields);
5556
}
5657

5758
public RowType(List<DataField> fields) {
@@ -163,106 +164,41 @@ public boolean equals(Object o) {
163164
return false;
164165
}
165166
RowType rowType = (RowType) o;
166-
return fields.equals(rowType.fields);
167-
}
168-
169-
@Override
170-
public int hashCode() {
171-
return Objects.hash(super.hashCode(), fields);
172-
}
173-
174-
/**
175-
* Compares this RowType with another RowType, ignoring field IDs.
176-
*
177-
* @param other the other RowType to compare with
178-
* @return true if the RowTypes are equal ignoring field IDs, false otherwise
179-
*/
180-
public boolean equalsIgnoreFieldId(RowType other) {
181-
if (this == other) {
182-
return true;
183-
}
184-
if (other == null) {
185-
return false;
186-
}
187-
if (this.isNullable() != other.isNullable()) {
188-
return false;
189-
}
190-
if (this.fields.size() != other.fields.size()) {
191-
return false;
192-
}
167+
// Compares this RowType with another RowType, ignoring field IDs.
193168
for (int i = 0; i < fields.size(); i++) {
194169
DataField thisField = fields.get(i);
195-
DataField otherField = other.fields.get(i);
196-
if (!thisField.getName().equals(otherField.getName())) {
197-
return false;
198-
}
199-
if (!thisField.getType().equals(otherField.getType())) {
200-
return false;
201-
}
202-
if (!Objects.equals(thisField.getDescription(), otherField.getDescription())) {
170+
DataField otherField = rowType.fields.get(i);
171+
if (!thisField.getName().equals(otherField.getName())
172+
|| !thisField.getType().equals(otherField.getType())
173+
|| !Objects.equals(thisField.getDescription(), otherField.getDescription())) {
203174
return false;
204175
}
205176
}
206177
return true;
207178
}
208179

180+
@Override
181+
public int hashCode() {
182+
return Objects.hash(super.hashCode(), fields);
183+
}
184+
209185
// --------------------------------------------------------------------------------------------
210186

211-
private static List<DataField> validateFields(List<DataField> fields) {
212-
// Validate field names
187+
private static void validateFields(List<DataField> fields) {
213188
final List<String> fieldNames =
214189
fields.stream().map(DataField::getName).collect(Collectors.toList());
215190
if (fieldNames.stream().anyMatch(StringUtils::isNullOrWhitespaceOnly)) {
216191
throw new IllegalArgumentException(
217192
"Field names must contain at least one non-whitespace character.");
218193
}
219-
final Set<String> duplicateNames =
194+
final Set<String> duplicates =
220195
fieldNames.stream()
221196
.filter(n -> Collections.frequency(fieldNames, n) > 1)
222197
.collect(Collectors.toSet());
223-
if (!duplicateNames.isEmpty()) {
198+
if (!duplicates.isEmpty()) {
224199
throw new IllegalArgumentException(
225-
String.format(
226-
"Field names must be unique. Found duplicates: %s", duplicateNames));
200+
String.format("Field names must be unique. Found duplicates: %s", duplicates));
227201
}
228-
229-
// Validate and process field IDs
230-
final List<Integer> fieldIds =
231-
fields.stream().map(DataField::getFieldId).collect(Collectors.toList());
232-
long negativeIdCount = fieldIds.stream().filter(id -> id == -1).count();
233-
234-
List<DataField> processedFields;
235-
if (negativeIdCount == fields.size()) {
236-
// All fields have ID -1, assign IDs in order
237-
processedFields = new ArrayList<>();
238-
for (int i = 0; i < fields.size(); i++) {
239-
DataField field = fields.get(i);
240-
processedFields.add(
241-
new DataField(
242-
field.getName(),
243-
field.getType(),
244-
field.getDescription().orElse(null),
245-
i));
246-
}
247-
} else if (negativeIdCount > 0) {
248-
// Some fields have ID -1 and some don't, throw error
249-
throw new IllegalArgumentException(
250-
"Field IDs must be either all -1 or all non-negative. "
251-
+ "Mixed field IDs are not allowed.");
252-
} else {
253-
final Set<Integer> duplicateIds =
254-
fieldIds.stream()
255-
.filter(id -> Collections.frequency(fieldIds, id) > 1)
256-
.collect(Collectors.toSet());
257-
if (!duplicateIds.isEmpty()) {
258-
throw new IllegalArgumentException(
259-
String.format(
260-
"Field IDs must be unique. Found duplicates: %s", duplicateIds));
261-
}
262-
processedFields = fields;
263-
}
264-
265-
return processedFields;
266202
}
267203

268204
public static RowType of(DataType... types) {
@@ -294,11 +230,7 @@ public static Builder builder() {
294230
}
295231

296232
public static Builder builder(boolean isNullable) {
297-
return new Builder(isNullable, new AtomicInteger(-1));
298-
}
299-
300-
public static Builder builder(boolean isNullable, AtomicInteger fieldId) {
301-
return new Builder(isNullable, fieldId);
233+
return new Builder(isNullable);
302234
}
303235

304236
/** Builder of {@link RowType}. */
@@ -307,20 +239,18 @@ public static class Builder {
307239
private final List<DataField> fields = new ArrayList<>();
308240

309241
private final boolean isNullable;
310-
private final AtomicInteger fieldId;
311242

312-
private Builder(boolean isNullable, AtomicInteger fieldId) {
243+
private Builder(boolean isNullable) {
313244
this.isNullable = isNullable;
314-
this.fieldId = fieldId;
315245
}
316246

317247
public Builder field(String name, DataType type) {
318-
fields.add(new DataField(name, type, fieldId.incrementAndGet()));
248+
fields.add(new DataField(name, type));
319249
return this;
320250
}
321251

322252
public Builder field(String name, DataType type, String description) {
323-
fields.add(new DataField(name, type, description, fieldId.incrementAndGet()));
253+
fields.add(new DataField(name, type, description));
324254
return this;
325255
}
326256

fluss-common/src/main/java/org/apache/fluss/utils/json/DataTypeJsonSerde.java

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -295,10 +295,6 @@ private static DataType deserializeRow(JsonNode dataTypeNode) {
295295
final ArrayNode fieldNodes = (ArrayNode) dataTypeNode.get(FIELD_NAME_FIELDS);
296296
final List<DataField> fields = new ArrayList<>();
297297

298-
boolean hasFieldWithId = false;
299-
boolean hasFieldWithoutId = false;
300-
int autoFieldId = 0;
301-
302298
for (JsonNode fieldNode : fieldNodes) {
303299
final String fieldName = fieldNode.get(FIELD_NAME_FIELD_NAME).asText();
304300
final DataType fieldType =
@@ -308,24 +304,13 @@ private static DataType deserializeRow(JsonNode dataTypeNode) {
308304
? fieldNode.get(FIELD_NAME_FIELD_DESCRIPTION).asText()
309305
: null;
310306

311-
final int fieldId;
312-
if (fieldNode.has(FIELD_NAME_FIELD_ID)) {
313-
hasFieldWithId = true;
314-
fieldId = fieldNode.get(FIELD_NAME_FIELD_ID).asInt();
315-
} else {
316-
hasFieldWithoutId = true;
317-
fieldId = autoFieldId++;
318-
}
319-
307+
final int fieldId =
308+
fieldNode.has(FIELD_NAME_FIELD_ID)
309+
? fieldNode.get(FIELD_NAME_FIELD_ID).asInt()
310+
: -1;
320311
fields.add(new DataField(fieldName, fieldType, fieldDescription, fieldId));
321312
}
322313

323-
if (hasFieldWithId && hasFieldWithoutId) {
324-
throw new TableException(
325-
"Field ID inconsistency detected in row type: "
326-
+ "all fields must either have field IDs or none should have field IDs.");
327-
}
328-
329314
return new RowType(fields);
330315
}
331316
}

0 commit comments

Comments
 (0)