Skip to content

Commit

Permalink
fix error model
Browse files Browse the repository at this point in the history
  • Loading branch information
kwadhwa18 committed Oct 12, 2022
1 parent 5a7591f commit bcae7f7
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 12 deletions.
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,12 @@
<version>3.12.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>4.2.0</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.apache.commons</groupId>
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/com/rockset/client/ApiClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.rockset.client.model.ErrorModel;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.squareup.okhttp.*;
import com.squareup.okhttp.internal.http.HttpMethod;
import com.squareup.okhttp.logging.HttpLoggingInterceptor;
Expand Down Expand Up @@ -53,7 +54,7 @@

public class ApiClient {

private String basePath = "https://api.rs2.usw2.rockset.com";
private String basePath = "https://api.use1a1.rockset.com";
private String apiKey;
private String version;
private boolean debugging = false;
Expand Down Expand Up @@ -108,7 +109,7 @@ public String getBasePath() {
/**
* Set base path
*
* @param basePath Base path of the URL (e.g https://api.rs2.usw2.rockset.com
* @param basePath Base path of the URL (e.g https://api.use1a1.rockset.com
* @return An instance of OkHttpClient
*/
public ApiClient setApiServer(String basePath) {
Expand Down Expand Up @@ -898,6 +899,7 @@ public <T> T handleResponse(Response response, Type returnType) throws Exception

final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS, true);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
errorModel = objectMapper.readValue(respBody, ErrorModel.class);

} catch (final IOException e) {
Expand Down
58 changes: 48 additions & 10 deletions src/main/java/com/rockset/jdbc/RocksetResultSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static java.math.BigDecimal.ROUND_HALF_UP;
import static java.util.Locale.ENGLISH;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.BooleanNode;
Expand Down Expand Up @@ -58,6 +59,7 @@

public class RocksetResultSet implements ResultSet {

static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
static final DateTimeFormatter DATE_FORMATTER = ISODateTimeFormat.date();
static final DateTimeFormatter TIME_FORMATTER = DateTimeFormat.forPattern("HH:mm:ss.SSS");
static final DateTimeFormatter TIMESTAMP_FORMATTER =
Expand Down Expand Up @@ -95,6 +97,10 @@ public class RocksetResultSet implements ResultSet {
private final List<Column> columns;
private final ResultSetMetaData resultSetMetaData;
private final AtomicInteger rowIndex = new AtomicInteger(-1);

// see next() and parseCurrentDocRootNode() -> we eagerly deserialize the raw Maps in the resultSet collection
// into JsonNodes whenever next() is called. On wide rows and large resultsets, this yields measurable performance benefit.
private JsonNode currentDocRootNode;
private final long maxRows;

private final int columnCount;
Expand Down Expand Up @@ -230,15 +236,17 @@ private boolean doNextIfPaginationEnabled() throws SQLException {

@Override
public boolean next() throws SQLException {
checkOpen();
this.rowIndex.getAndIncrement();
boolean hasNext = doNext();

if (this.rocksetResultSetPaginationParams != null
&& this.rocksetResultSetPaginationParams.getFetchSize() > 0) {
return doNextIfPaginationEnabled();
if (hasNext) {
// eagerly parse the current row
currentDocRootNode = parseCurrentDocRootNode();
} else {
// nothing to parse -> nullify in case we use it elsewhere and the tests will reveal an NPE!
currentDocRootNode = null;
}

return doNextIfPaginationDisabled();
return hasNext;
}

@Override
Expand Down Expand Up @@ -1387,10 +1395,7 @@ private JsonNode column(int index) throws SQLException {
String columnName = columnInfo(index).getName();
// extract the row
try {
ObjectMapper mapper = new ObjectMapper();
Object onedoc = resultSet.get(rowIndex.get());
JsonNode docRootNode = mapper.readTree(mapper.writeValueAsString(onedoc));
JsonNode value = docRootNode.get(columnName);
JsonNode value = currentDocRootNode.get(columnName);
wasNull.set((value == null) || (value instanceof NullNode));
return value;
} catch (Exception e) {
Expand Down Expand Up @@ -1608,4 +1613,37 @@ private static Map<String, Integer> getFieldMap(List<Column> columns) {
}
return ImmutableMap.copyOf(map);
}

private boolean doNext() throws SQLException {
checkOpen();
this.rowIndex.getAndIncrement();

if (this.rocksetResultSetPaginationParams != null
&& this.rocksetResultSetPaginationParams.getFetchSize() > 0) {
return doNextIfPaginationEnabled();
}

return doNextIfPaginationDisabled();
}

/**
* Two-step parse of the row at the current index, in the resultSet.
*
* @return JsonNode encapsulating the parsed row
* @throws SQLException if unable to parse the row
*/
private JsonNode parseCurrentDocRootNode() throws SQLException {
int index = rowIndex.get();

Object onedoc = resultSet.get(index);

try {
String asJson = OBJECT_MAPPER.writeValueAsString(onedoc);

return OBJECT_MAPPER.readTree(asJson);
} catch (JsonProcessingException e) {
throw new SQLException(
"Error caching document root node at row index " + index, e);
}
}
}
25 changes: 25 additions & 0 deletions src/test/java/com/rockset/client/api/TestResponseMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.rockset.client.api;

import com.rockset.client.ApiClient;
import com.rockset.client.ApiException;
import com.squareup.okhttp.Response;
import com.squareup.okhttp.ResponseBody;
import org.mockito.Mockito;
import org.testng.Assert;
import org.testng.annotations.Test;

public class TestResponseMapper {
@Test
public void testUnknownProps() throws Exception {
ApiClient apiClient = new ApiClient();
Response response = Mockito.mock(Response.class);
Mockito.when(response.isSuccessful()).thenReturn(false);

ResponseBody body = Mockito.mock(ResponseBody.class);
Mockito.when(body.string()).thenReturn("{ \"message\" : \"invalid\", \"unknown_field\" : \"foo\" }");
Mockito.when(response.body()).thenReturn(body);

ApiException e = Assert.expectThrows(ApiException.class, () -> apiClient.handleResponse(response, null));
Assert.assertEquals(e.getErrorModel().getMessage(), "invalid");
}
}

0 comments on commit bcae7f7

Please sign in to comment.