Skip to content

Commit 3f5c509

Browse files
fix(aws-datastore): store schema float as a java double (#1040)
The Amplify DataStore leverages GraphQL to define its data models. Therefor, our intention is to support a strict superset of the primitive types described by the GraphQL specification. While implementing the DataStore, we overlooked that the GraphQL "Float" type is a double-precision value. The SQL adapter is able to accomodate this, currently. However, our Java codegen stores a float value, and we look for values of Float type while serializing and deserializing object data. Unfortunately, we need to continue to support that behavior, since customers will have Float values in their models. None-the-less, the Flutter consumer of this library rightly wants to use the actual GraphQL scalar types, and see the same behavior accross iOS and Android. As a result of these constraints, we must support both types in the library, for now. The decision to express a floating point value as a Java Float or Double will be taken from the type of the value in the model object. For our Java models, it will be a Float. When Map data is passed from Flutter, it will be a Double. Both SQL and AppSync will treat both as a double, which is large enough to accomodate both types. Or in other words, both types are supported, now. The next step will be to update the Java codegen, so that it represents GraphQL Float types as Java Doubles. This change will allow new customers to use the fix, while we continue to support existing customers' models. Resolves: #1031
1 parent 092ce2c commit 3f5c509

File tree

8 files changed

+19
-6
lines changed

8 files changed

+19
-6
lines changed

aws-api-appsync/src/main/java/com/amplifyframework/core/model/types/JavaFieldType.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ public enum JavaFieldType {
4646
*/
4747
FLOAT(Float.class),
4848

49+
/**
50+
* Represents the double data type.
51+
*/
52+
DOUBLE(Double.class),
53+
4954
/**
5055
* Represents the String data type.
5156
*/

aws-api-appsync/src/main/java/com/amplifyframework/util/GsonObjectConverter.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,10 @@ private static Object toObject(JsonElement element) {
7575
Number number = primitive.getAsNumber();
7676
if (number.floatValue() == number.intValue()) {
7777
return number.intValue();
78-
} else {
78+
} else if (number.floatValue() == number.doubleValue()) {
7979
return number.floatValue();
80+
} else {
81+
return number.doubleValue();
8082
}
8183
} else if (primitive.isBoolean()) {
8284
return primitive.getAsBoolean();

aws-datastore/src/main/java/com/amplifyframework/datastore/appsync/AWSAppSyncScalarType.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public enum AWSAppSyncScalarType {
4444

4545
/**
4646
* A signed double-precision fractional values as specified by IEEE 754.
47+
* Note that this is distinct from a {@link java.lang.Float}, which stores a single precision value.
4748
* @see <a href="https://docs.aws.amazon.com/appsync/latest/devguide/scalars.html#float">Float Scalar</a>
4849
*/
4950
FLOAT("Float"),

aws-datastore/src/main/java/com/amplifyframework/datastore/storage/sqlite/SQLiteDataType.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ public enum SQLiteDataType {
3333
INTEGER("INTEGER"),
3434

3535
/**
36-
* The value is a floating point value, stored as an 8-byte IEEE
37-
* floating point number.
36+
* The value is a floating point value, stored as an 8-byte ("double precision")
37+
* IEEE floating point number.
3838
*/
3939
REAL("REAL"),
4040

aws-datastore/src/main/java/com/amplifyframework/datastore/storage/sqlite/SQLiteModelFieldTypeConverter.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ public static Object convertRawValueToTarget(
9191
case INTEGER:
9292
case LONG:
9393
case FLOAT:
94+
case DOUBLE:
9495
case STRING:
9596
// these types require no special treatment
9697
return value;
@@ -172,6 +173,8 @@ public Object convertValueFromSource(
172173
return cursor.getInt(columnIndex) != 0;
173174
case FLOAT:
174175
return cursor.getFloat(columnIndex);
176+
case DOUBLE:
177+
return cursor.getDouble(columnIndex);
175178
case LONG:
176179
return cursor.getLong(columnIndex);
177180
case DATE:

aws-datastore/src/main/java/com/amplifyframework/datastore/storage/sqlite/SQLiteStorageAdapter.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,8 @@ private void bindValueToStatement(
713713
statement.bindLong(columnIndex, (Integer) value);
714714
} else if (value instanceof Float) {
715715
statement.bindDouble(columnIndex, (Float) value);
716+
} else if (value instanceof Double) {
717+
statement.bindDouble(columnIndex, (Double) value);
716718
} else {
717719
throw new DataStoreException("", "");
718720
}

aws-datastore/src/main/java/com/amplifyframework/datastore/storage/sqlite/TypeConverter.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ private TypeConverter() {
4242
JAVA_TO_SQL.put(JavaFieldType.LONG, SQLiteDataType.INTEGER);
4343
JAVA_TO_SQL.put(JavaFieldType.INTEGER, SQLiteDataType.INTEGER);
4444
JAVA_TO_SQL.put(JavaFieldType.FLOAT, SQLiteDataType.REAL);
45+
JAVA_TO_SQL.put(JavaFieldType.DOUBLE, SQLiteDataType.REAL);
4546
JAVA_TO_SQL.put(JavaFieldType.STRING, SQLiteDataType.TEXT);
4647
JAVA_TO_SQL.put(JavaFieldType.ENUM, SQLiteDataType.TEXT);
4748
JAVA_TO_SQL.put(JavaFieldType.DATE, SQLiteDataType.TEXT);

aws-datastore/src/test/java/com/amplifyframework/datastore/appsync/AppSyncConflictUnhandledErrorTest.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,8 @@ public void conflictErrorExtractedIfPresent() {
119119
AppSyncConflictUnhandledError.findFirst(Note.class, response.getErrors());
120120
assertNotNull(conflictUnhandledError);
121121

122-
// TODO: The JSON document has '1601499066604' as the time. These differ by 26604,
123-
// also the TimeUnit appears to be wrong. Should be MILLISECONDS.
124-
Temporal.Timestamp lastChangedAt = new Temporal.Timestamp(1601499040000L, TimeUnit.SECONDS);
122+
// TODO: the TimeUnit appears to be wrong. Should be MILLISECONDS?
123+
Temporal.Timestamp lastChangedAt = new Temporal.Timestamp(1601499066604L, TimeUnit.SECONDS);
125124
assertEquals(
126125
new ModelWithMetadata<>(
127126
new Note("KoolId22", "Resurecting the dataz"),

0 commit comments

Comments
 (0)