Skip to content

Commit 91520c4

Browse files
authored
Chore: use Locale.ROOT in String.format. (#3117)
Use `String.format` in locale-neutral to avoid rendering message in an unexpected way when the JVM process is configured with a specific locale such as `lrc_IR`. This fixes #3121.
1 parent 2dbe4f6 commit 91520c4

File tree

53 files changed

+198
-148
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+198
-148
lines changed

docs/ReleaseNotes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Users performing online updates are encouraged to update from [4.0.559.4](#40559
2121
2222
* **Bug fix** Fix 1 [(Issue #NNN)](https://github.com/FoundationDB/fdb-record-layer/issues/NNN)
2323
* **Bug fix** Fix 2 [(Issue #NNN)](https://github.com/FoundationDB/fdb-record-layer/issues/NNN)
24+
* **Bug fix** The relational component now specifies `Locale.ROOT` in all usages of `String.format` which may change number formatting if the default locale does not align [(Issue #3121)](https://github.com/FoundationDB/fdb-record-layer/issues/3121)
2425
* **Bug fix** Fix 3 [(Issue #NNN)](https://github.com/FoundationDB/fdb-record-layer/issues/NNN)
2526
* **Bug fix** Fix 4 [(Issue #NNN)](https://github.com/FoundationDB/fdb-record-layer/issues/NNN)
2627
* **Bug fix** Fix 5 [(Issue #NNN)](https://github.com/FoundationDB/fdb-record-layer/issues/NNN)

fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/EmbeddedRelationalStruct.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import java.sql.Types;
3232
import java.util.ArrayList;
3333
import java.util.List;
34+
import java.util.Locale;
3435

3536
public interface EmbeddedRelationalStruct extends RelationalStruct {
3637

@@ -88,15 +89,15 @@ public Builder addString(String fieldName, @Nullable String s) throws SQLExcepti
8889
public RelationalStructBuilder addObject(String fieldName, @Nullable Object obj, int targetSqlType) throws SQLException {
8990
if (targetSqlType == Types.STRUCT) {
9091
if (!(obj instanceof RelationalStruct)) {
91-
throw new RelationalException(String.format("Expected object to be of type:STRUCT, but found type:%s",
92+
throw new RelationalException(String.format(Locale.ROOT, "Expected object to be of type:STRUCT, but found type:%s",
9293
obj == null ? "<NULL>" : SqlTypeNamesSupport.getSqlTypeName(SqlTypeSupport.getSqlTypeCodeFromObject(obj))),
9394
ErrorCode.DATATYPE_MISMATCH).toSqlException();
9495
}
9596
return addStruct(fieldName, (RelationalStruct) obj);
9697
}
9798
if (targetSqlType == Types.ARRAY) {
9899
if (!(obj instanceof RelationalArray)) {
99-
throw new RelationalException(String.format("Expected object to be of type:ARRAY, but found type:%s",
100+
throw new RelationalException(String.format(Locale.ROOT, "Expected object to be of type:ARRAY, but found type:%s",
100101
obj == null ? "<NULL>" : SqlTypeNamesSupport.getSqlTypeName(SqlTypeSupport.getSqlTypeCodeFromObject(obj))),
101102
ErrorCode.DATATYPE_MISMATCH).toSqlException();
102103
}

fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ProtobufDataBuilder.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636
import javax.annotation.Nonnull;
3737
import java.sql.SQLException;
38+
import java.util.Locale;
3839
import java.util.Set;
3940
import java.util.stream.Collectors;
4041

@@ -61,7 +62,7 @@ public Set<String> getFieldNames() {
6162
public String getFieldType(String fieldName) throws SQLException {
6263
final Descriptors.FieldDescriptor field = typeDescriptor.findFieldByName(fieldName);
6364
if (field == null) {
64-
throw new RelationalException(String.format("Field <%s> does not exist", fieldName), ErrorCode.INVALID_PARAMETER).toSqlException();
65+
throw new RelationalException(String.format(Locale.ROOT, "Field <%s> does not exist", fieldName), ErrorCode.INVALID_PARAMETER).toSqlException();
6566
}
6667
return ProtobufDdlUtil.getTypeName(field);
6768
}
@@ -71,7 +72,7 @@ public String getFieldType(String fieldName) throws SQLException {
7172
public boolean isPrimitive(int fieldNumber) throws SQLException {
7273
final var field = typeDescriptor.getFields().get(fieldNumber - 1);
7374
if (field == null) {
74-
throw new RelationalException(String.format("Field with number <%d> does not exist", fieldNumber), ErrorCode.INVALID_PARAMETER).toSqlException();
75+
throw new RelationalException(String.format(Locale.ROOT, "Field with number <%d> does not exist", fieldNumber), ErrorCode.INVALID_PARAMETER).toSqlException();
7576
}
7677
return !field.isRepeated() && !field.getJavaType().equals(Descriptors.FieldDescriptor.JavaType.MESSAGE); // enum?
7778
}
@@ -81,7 +82,7 @@ public DynamicMessageBuilder setField(String fieldName, Object value) throws SQL
8182
try {
8283
final Descriptors.FieldDescriptor field = typeDescriptor.findFieldByName(fieldName);
8384
if (field == null) {
84-
throw new RelationalException(String.format("Field <%s> does not exist", fieldName), ErrorCode.INVALID_PARAMETER);
85+
throw new RelationalException(String.format(Locale.ROOT, "Field <%s> does not exist", fieldName), ErrorCode.INVALID_PARAMETER);
8586
}
8687
return setFieldInternal(field, value);
8788
} catch (RelationalException e) {
@@ -95,7 +96,7 @@ public DynamicMessageBuilder setField(int fieldNumber, Object value) throws SQLE
9596
try {
9697
final Descriptors.FieldDescriptor field = typeDescriptor.getFields().get(fieldNumber - 1);
9798
if (field == null) {
98-
throw new RelationalException(String.format("Field with number (%d) does not exist", fieldNumber), ErrorCode.INVALID_PARAMETER);
99+
throw new RelationalException(String.format(Locale.ROOT, "Field with number (%d) does not exist", fieldNumber), ErrorCode.INVALID_PARAMETER);
99100
}
100101
return setFieldInternal(field, value);
101102
} catch (RelationalException e) {
@@ -130,7 +131,7 @@ public DynamicMessageBuilder addRepeatedField(int fieldNumber, Object value) thr
130131
try {
131132
final Descriptors.FieldDescriptor field = typeDescriptor.getFields().get(fieldNumber - 1);
132133
if (field == null) {
133-
throw new RelationalException(String.format("Field with number (%d) does not exist", fieldNumber), ErrorCode.INVALID_PARAMETER);
134+
throw new RelationalException(String.format(Locale.ROOT, "Field with number (%d) does not exist", fieldNumber), ErrorCode.INVALID_PARAMETER);
134135
}
135136
if (!field.isRepeated()) {
136137
throw new RelationalException("Field with number <" + fieldNumber + "> is not repeated", ErrorCode.INVALID_PARAMETER);

fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/RowStruct.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import java.sql.Types;
3737
import java.util.ArrayList;
3838
import java.util.Collection;
39+
import java.util.Locale;
3940

4041
/**
4142
* Implementation of {@link RelationalStruct} that is backed by a {@link Row}.
@@ -107,7 +108,7 @@ public int getInt(int oneBasedPosition) throws SQLException {
107108
return 0;
108109
}
109110
if (!(o instanceof Number)) {
110-
throw new SQLException(String.format("Cannot convert %s to Integer", o.getClass().toString()), ErrorCode.CANNOT_CONVERT_TYPE.getErrorCode());
111+
throw new SQLException(String.format(Locale.ROOT, "Cannot convert %s to Integer", o.getClass().toString()), ErrorCode.CANNOT_CONVERT_TYPE.getErrorCode());
111112
}
112113

113114
return ((Number) o).intValue();
@@ -125,7 +126,7 @@ public long getLong(int oneBasedPosition) throws SQLException {
125126
return 0L;
126127
}
127128
if (!(o instanceof Number)) {
128-
throw new SQLException(String.format("Cannot convert %s to Long", o.getClass().toString()), ErrorCode.CANNOT_CONVERT_TYPE.getErrorCode());
129+
throw new SQLException(String.format(Locale.ROOT, "Cannot convert %s to Long", o.getClass().toString()), ErrorCode.CANNOT_CONVERT_TYPE.getErrorCode());
129130
}
130131

131132
return ((Number) o).longValue();

fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/metrics/MetricCollector.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.apple.foundationdb.relational.util.Supplier;
2626

2727
import javax.annotation.Nonnull;
28+
import java.util.Locale;
2829

2930
/**
3031
* MetricCollector provides a utility API to register events and counts while performing operations in the Relational
@@ -65,7 +66,7 @@ public interface MetricCollector {
6566
* @throws RelationalException in case the requested event is not held in the collector.
6667
* */
6768
default double getAverageTimeMicrosForEvent(@Nonnull RelationalMetric.RelationalEvent event) throws RelationalException {
68-
throw new RelationalException(String.format("Requested event metric: %s is not in the collector", event.title()), ErrorCode.INTERNAL_ERROR);
69+
throw new RelationalException(String.format(Locale.ROOT, "Requested event metric: %s is not in the collector", event.title()), ErrorCode.INTERNAL_ERROR);
6970
}
7071

7172
/**
@@ -76,7 +77,7 @@ default double getAverageTimeMicrosForEvent(@Nonnull RelationalMetric.Relational
7677
* @throws RelationalException in case the requested count is not held in the collector.
7778
* */
7879
default long getCountsForCounter(@Nonnull RelationalMetric.RelationalCount count) throws RelationalException {
79-
throw new RelationalException(String.format("Requested count metric: %s is not in the collector", count.title()), ErrorCode.INTERNAL_ERROR);
80+
throw new RelationalException(String.format(Locale.ROOT, "Requested count metric: %s is not in the collector", count.title()), ErrorCode.INTERNAL_ERROR);
8081
}
8182

8283
/**

fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/metrics/RelationalMetric.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public enum RelationalEvent implements StoreTimer.Event {
8080
private final String logKey;
8181

8282
RelationalEvent(String title) {
83-
this.title = String.format("%s %s", RELATIONAL_TITLE_PREFIX, title);
83+
this.title = RELATIONAL_TITLE_PREFIX + " " + title;
8484
this.logKey = RELATIONAL_LOG_PREFIX + StoreTimer.Event.super.logKey();
8585
}
8686

@@ -111,7 +111,7 @@ public enum RelationalCount implements StoreTimer.Count {
111111
private final String logKey;
112112

113113
RelationalCount(String title, boolean isSize) {
114-
this.title = String.format("%s %s", RELATIONAL_TITLE_PREFIX, title);
114+
this.title = RELATIONAL_TITLE_PREFIX + " " + title;
115115
this.logKey = RELATIONAL_LOG_PREFIX + StoreTimer.Count.super.logKey();
116116
this.isSize = isSize;
117117
}

fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ContinuationImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636
import javax.annotation.Nonnull;
3737
import javax.annotation.Nullable;
38+
import java.util.Locale;
3839
import java.util.Objects;
3940

4041
@API(API.Status.EXPERIMENTAL)
@@ -198,7 +199,7 @@ public static ContinuationImpl copyOf(@Nonnull Continuation other) throws Relati
198199
} else if (other.atEnd()) {
199200
return END;
200201
} else {
201-
String message = String.format("programming error, extra logic required for copy-constructing from %s", other.getClass());
202+
String message = String.format(Locale.ROOT, "programming error, extra logic required for copy-constructing from %s", other.getClass());
202203
assert false : message;
203204
throw new RelationalException(message, ErrorCode.INTERNAL_ERROR); // -ea safety net.
204205
}

fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalConnection.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
import java.sql.Types;
7575
import java.util.ArrayList;
7676
import java.util.Arrays;
77+
import java.util.Locale;
7778
import java.util.stream.Collectors;
7879

7980
/**
@@ -272,7 +273,7 @@ void setSchema(@Nullable String schema, boolean checkSchemaExists) throws SQLExc
272273
private void checkSchemaExists(@Nonnull String schema) throws SQLException {
273274
runIsolatedInTransactionIfPossible(() -> {
274275
if (!this.backingCatalog.doesSchemaExist(getTransaction(), getRecordLayerDatabase().getURI(), schema)) {
275-
throw new RelationalException(String.format("Schema %s does not exist in %s", schema, getPath()), ErrorCode.UNDEFINED_SCHEMA);
276+
throw new RelationalException(String.format(Locale.ROOT, "Schema %s does not exist in %s", schema, getPath()), ErrorCode.UNDEFINED_SCHEMA);
276277
}
277278
return null;
278279
});

fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalPreparedStatement.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import javax.annotation.Nonnull;
3636
import java.sql.Array;
3737
import java.sql.SQLException;
38+
import java.util.Locale;
3839
import java.util.Map;
3940
import java.util.TreeMap;
4041

@@ -58,15 +59,15 @@ public RelationalResultSet executeQuery() throws SQLException {
5859
if (execute()) {
5960
return currentResultSet;
6061
} else {
61-
throw new SQLException(String.format("query '%s' does not return result set, use JDBC executeUpdate method instead", sql), ErrorCode.NO_RESULT_SET.getErrorCode());
62+
throw new SQLException(String.format(Locale.ROOT, "query '%s' does not return result set, use JDBC executeUpdate method instead", sql), ErrorCode.NO_RESULT_SET.getErrorCode());
6263
}
6364
}
6465

6566
@Override
6667
public int executeUpdate() throws SQLException {
6768
checkOpen();
6869
if (execute()) {
69-
throw new SQLException(String.format("query '%s' returns a result set, use JDBC executeQuery method instead", sql), ErrorCode.EXECUTE_UPDATE_RETURNED_RESULT_SET.getErrorCode());
70+
throw new SQLException(String.format(Locale.ROOT, "query '%s' returns a result set, use JDBC executeQuery method instead", sql), ErrorCode.EXECUTE_UPDATE_RETURNED_RESULT_SET.getErrorCode());
7071
}
7172
return currentRowCount;
7273
}

fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/EmbeddedRelationalStatement.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import java.util.Collections;
4747
import java.util.Iterator;
4848
import java.util.List;
49+
import java.util.Locale;
4950
import java.util.Map;
5051
import java.util.Set;
5152

@@ -80,15 +81,15 @@ public RelationalResultSet executeQuery(String sql) throws SQLException {
8081
if (execute(sql)) {
8182
return getResultSet();
8283
} else {
83-
throw new SQLException(String.format("query '%s' does not return result set, use JDBC executeUpdate method instead", sql), ErrorCode.NO_RESULT_SET.getErrorCode());
84+
throw new SQLException(String.format(Locale.ROOT, "query '%s' does not return result set, use JDBC executeUpdate method instead", sql), ErrorCode.NO_RESULT_SET.getErrorCode());
8485
}
8586
}
8687

8788
@Override
8889
public int executeUpdate(String sql) throws SQLException {
8990
checkOpen();
9091
if (execute(sql)) {
91-
throw new SQLException(String.format("query '%s' returns a result set, use JDBC executeQuery method instead", sql), ErrorCode.EXECUTE_UPDATE_RETURNED_RESULT_SET.getErrorCode());
92+
throw new SQLException(String.format(Locale.ROOT, "query '%s' returns a result set, use JDBC executeQuery method instead", sql), ErrorCode.EXECUTE_UPDATE_RETURNED_RESULT_SET.getErrorCode());
9293
}
9394
return currentRowCount;
9495
}

0 commit comments

Comments
 (0)