fix: 9414 Firestore where clause not fetching numbers (#10775)

* Fixed issue with Firestore in fetching data while using numbers in the where condition.
* Other Fixes made in the where condition :
  When using Boolean
  When using Date 
  When Using Timestamp 
  When given space in the key
  When Space given in the Value
This commit is contained in:
Leo Thomas 2022-02-08 16:59:50 +05:30 committed by GitHub
parent da655b5748
commit 6e7687450e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 236 additions and 4 deletions

View File

@ -1,14 +1,18 @@
package com.external.utils;
import com.appsmith.external.constants.DataType;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException;
import com.appsmith.external.constants.ConditionalOperator;
import com.appsmith.external.helpers.DataTypeStringUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.cloud.firestore.FieldPath;
import com.google.cloud.firestore.Query;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
@ -16,7 +20,9 @@ public class WhereConditionUtils {
protected static final ObjectMapper objectMapper = new ObjectMapper();
public static Query applyWhereConditional(Query query, String path, String operatorString, String value) throws AppsmithPluginException {
public static Query applyWhereConditional(Query query, String strPath, String operatorString, String strValue) throws AppsmithPluginException {
String path = strPath.trim();
if (query == null) {
throw new AppsmithPluginException(
@ -37,6 +43,44 @@ public class WhereConditionUtils {
);
}
DataType dataType = DataTypeStringUtils.stringToKnownDataTypeConverter(strValue);
Object value = strValue.trim();
switch (dataType) {
case INTEGER:
case LONG:
case FLOAT:
case DOUBLE:
value = Double.parseDouble(strValue);
break;
case BOOLEAN:
value = Boolean.parseBoolean(strValue);
break;
case DATE:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
java.util.Date date = null;
try {
date = sdf.parse(strValue);
} catch (ParseException e) {
//Input may not be of above pattern
}
value = date;
break;
case TIMESTAMP:
SimpleDateFormat sdfTs = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
java.util.Date timeStamp = null;
try {
timeStamp = sdfTs.parse(strValue);
} catch (ParseException e) {
//Input may not be of above pattern
}
value = timeStamp;
break;
}
FieldPath fieldPath = FieldPath.of(path.split("\\."));
switch (operator) {
case LT:
@ -56,7 +100,7 @@ public class WhereConditionUtils {
return query.whereArrayContains(fieldPath, value);
case ARRAY_CONTAINS_ANY:
try {
return query.whereArrayContainsAny(fieldPath, parseList(value));
return query.whereArrayContainsAny(fieldPath, parseList((String) value));
} catch (IOException e) {
throw new AppsmithPluginException(
AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR,
@ -65,7 +109,7 @@ public class WhereConditionUtils {
}
case IN:
try {
return query.whereIn(fieldPath, parseList(value));
return query.whereIn(fieldPath, parseList((String) value));
} catch (IOException e) {
throw new AppsmithPluginException(
AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR,

View File

@ -14,6 +14,7 @@ import com.appsmith.external.models.Property;
import com.appsmith.external.models.RequestParamDTO;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.api.client.util.DateTime;
import com.google.cloud.NoCredentials;
import com.google.cloud.ServiceOptions;
import com.google.cloud.firestore.Blob;
@ -33,6 +34,9 @@ import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import java.nio.charset.StandardCharsets;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@ -79,7 +83,7 @@ public class FirestorePluginTest {
static DatasourceConfiguration dsConfig = new DatasourceConfiguration();
@BeforeClass
public static void setUp() throws ExecutionException, InterruptedException {
public static void setUp() throws ExecutionException, InterruptedException, ParseException {
firestoreConnection = FirestoreOptions.newBuilder()
.setHost(emulator.getEmulatorEndpoint())
.setCredentials(NoCredentials.getInstance())
@ -115,6 +119,14 @@ public class FirestorePluginTest {
)
)).get();
final Map<String, Object> numData = new HashMap<>(Map.of(
"score", Integer.valueOf("99"),
"isPlural", Boolean.TRUE,
"dob", new SimpleDateFormat("yyyy-MM-dd").parse("2000-03-24"),
"start", Timestamp.valueOf("2018-09-01 09:01:15")
));
firestoreConnection.document("numeric/two").set(numData).get();
firestoreConnection.document("changing/to-update").set(Map.of("value", 1)).get();
firestoreConnection.document("changing/to-delete").set(Map.of("value", 1)).get();
@ -785,6 +797,182 @@ public class FirestorePluginTest {
.verifyComplete();
}
@Test
public void testNumberWhereConditional() {
Map<String, Object> configMap = new HashMap<>();
setValueSafelyInFormData(configMap, COMMAND, "GET_COLLECTION");
List<Object> children = new ArrayList<>();
children.add(new HashMap<String, Object>() {{
put("key", "{{Input1.text}}");
put("condition", "EQ");
put("value", "{{Input2.text}}");
}});
Map<String, Object> whereMap = new HashMap<>();
whereMap.put(CHILDREN, children);
setValueSafelyInFormData(configMap, WHERE, whereMap);
ActionConfiguration actionConfiguration = new ActionConfiguration();
actionConfiguration.setPath("numeric");
actionConfiguration.setFormData(configMap);
List params = new ArrayList();
Param param = new Param();
param.setKey("Input1.text");
param.setValue("score");
params.add(param);
param = new Param();
param.setKey("Input2.text");
param.setValue("99");
params.add(param);
ExecuteActionDTO executeActionDTO = new ExecuteActionDTO();
executeActionDTO.setParams(params);
Mono<ActionExecutionResult> resultMono = pluginExecutor
.executeParameterized(firestoreConnection, executeActionDTO, dsConfig, actionConfiguration);
StepVerifier.create(resultMono)
.assertNext(result -> {
assertTrue(result.getIsExecutionSuccess());
List<Map<String, Object>> results = (List) result.getBody();
assertEquals(1, results.size());
})
.verifyComplete();
}
@Test
public void testBooleanWhereConditional() {
Map<String, Object> configMap = new HashMap<>();
setValueSafelyInFormData(configMap, COMMAND, "GET_COLLECTION");
List<Object> children = new ArrayList<>();
children.add(new HashMap<String, Object>() {{
put("key", "{{Input1.text}}");
put("condition", "EQ");
put("value", "{{Input2.text}}");
}});
Map<String, Object> whereMap = new HashMap<>();
whereMap.put(CHILDREN, children);
setValueSafelyInFormData(configMap, WHERE, whereMap);
ActionConfiguration actionConfiguration = new ActionConfiguration();
actionConfiguration.setPath("numeric");
actionConfiguration.setFormData(configMap);
List params = new ArrayList();
Param param = new Param();
param.setKey("Input1.text");
param.setValue("isPlural");
params.add(param);
param = new Param();
param.setKey("Input2.text");
param.setValue("true");
params.add(param);
ExecuteActionDTO executeActionDTO = new ExecuteActionDTO();
executeActionDTO.setParams(params);
Mono<ActionExecutionResult> resultMono = pluginExecutor
.executeParameterized(firestoreConnection, executeActionDTO, dsConfig, actionConfiguration);
StepVerifier.create(resultMono)
.assertNext(result -> {
assertTrue(result.getIsExecutionSuccess());
List<Map<String, Object>> results = (List) result.getBody();
assertEquals(1, results.size());
})
.verifyComplete();
}
@Test
public void testDateWhereConditional() {
Map<String, Object> configMap = new HashMap<>();
setValueSafelyInFormData(configMap, COMMAND, "GET_COLLECTION");
List<Object> children = new ArrayList<>();
children.add(new HashMap<String, Object>() {{
put("key", "{{Input1.text}}");
put("condition", "EQ");
put("value", "{{Input2.text}}");
}});
Map<String, Object> whereMap = new HashMap<>();
whereMap.put(CHILDREN, children);
setValueSafelyInFormData(configMap, WHERE, whereMap);
ActionConfiguration actionConfiguration = new ActionConfiguration();
actionConfiguration.setPath("numeric");
actionConfiguration.setFormData(configMap);
List params = new ArrayList();
Param param = new Param();
param.setKey("Input1.text");
param.setValue("dob");
params.add(param);
param = new Param();
param.setKey("Input2.text");
param.setValue("2000-03-24");
params.add(param);
ExecuteActionDTO executeActionDTO = new ExecuteActionDTO();
executeActionDTO.setParams(params);
Mono<ActionExecutionResult> resultMono = pluginExecutor
.executeParameterized(firestoreConnection, executeActionDTO, dsConfig, actionConfiguration);
StepVerifier.create(resultMono)
.assertNext(result -> {
assertTrue(result.getIsExecutionSuccess());
List<Map<String, Object>> results = (List) result.getBody();
assertEquals(1, results.size());
})
.verifyComplete();
}
@Test
public void testTimeStampWhereConditional() {
Map<String, Object> configMap = new HashMap<>();
setValueSafelyInFormData(configMap, COMMAND, "GET_COLLECTION");
List<Object> children = new ArrayList<>();
children.add(new HashMap<String, Object>() {{
put("key", "{{Input1.text}}");
put("condition", "EQ");
put("value", "{{Input2.text}}");
}});
Map<String, Object> whereMap = new HashMap<>();
whereMap.put(CHILDREN, children);
setValueSafelyInFormData(configMap, WHERE, whereMap);
ActionConfiguration actionConfiguration = new ActionConfiguration();
actionConfiguration.setPath("numeric");
actionConfiguration.setFormData(configMap);
List params = new ArrayList();
Param param = new Param();
param.setKey("Input1.text");
param.setValue("start");
params.add(param);
param = new Param();
param.setKey("Input2.text");
param.setValue("2018-09-01 09:01:15");
params.add(param);
ExecuteActionDTO executeActionDTO = new ExecuteActionDTO();
executeActionDTO.setParams(params);
Mono<ActionExecutionResult> resultMono = pluginExecutor
.executeParameterized(firestoreConnection, executeActionDTO, dsConfig, actionConfiguration);
StepVerifier.create(resultMono)
.assertNext(result -> {
assertTrue(result.getIsExecutionSuccess());
List<Map<String, Object>> results = (List) result.getBody();
assertEquals(1, results.size());
})
.verifyComplete();
}
@Test
public void testUpdateDocumentWithFieldValueTimestamp() {