This is an automated email from the ASF dual-hosted git repository. imaxon pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/asterixdb.git
commit 528ee18a5a7d9c01aa1f3f94282fbff2063f688a Author: Michael Blow <mb...@apache.org> AuthorDate: Wed May 19 20:10:46 2021 -0400 [NO ISSUE][*DB][EXT] Fail with helpful error message on non-JSON object Change-Id: Ia096e108aa062e87a92f29ad3812f118390f411e Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/11525 Integration-Tests: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Reviewed-by: Till Westmann <ti...@apache.org> Tested-by: Jenkins <jenk...@fulliautomatix.ics.uci.edu> --- .../java/org/apache/asterix/common/exceptions/ErrorCode.java | 3 ++- .../src/main/resources/asx_errormsg/en.properties | 1 + .../asterix/external/parser/AbstractJsonDataParser.java | 11 ++++++++--- .../asterix/external/parser/AbstractNestedDataParser.java | 2 +- .../org/apache/asterix/external/parser/JSONDataParser.java | 6 +++++- .../org/apache/asterix/external/parser/ParseException.java | 4 ++++ .../java/org/apache/asterix/external/parser/TweetParser.java | 2 +- .../java/org/apache/hyracks/api/util/ErrorMessageUtil.java | 11 +++++++---- 8 files changed, 29 insertions(+), 11 deletions(-) diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java index 7e32e0b..4078ea2 100644 --- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java +++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java @@ -307,7 +307,7 @@ public enum ErrorCode implements IError { PARSER_ADM_DATA_PARSER_CAST_ERROR(3072), PARSER_ADM_DATA_PARSER_CONSTRUCTOR_MISSING_DESERIALIZER(3073), PARSER_ADM_DATA_PARSER_WRONG_INSTANCE(3074), - PARSER_TWEET_PARSER_CLOSED_FIELD_NULL(3075), + PARSER_EXT_DATA_PARSER_CLOSED_FIELD_NULL(3075), UTIL_FILE_SYSTEM_WATCHER_NO_FILES_FOUND(3076), UTIL_LOCAL_FILE_SYSTEM_UTILS_PATH_NOT_FOUND(3077), UTIL_HDFS_UTILS_CANNOT_OBTAIN_HDFS_SCHEDULER(3078), @@ -349,6 +349,7 @@ public enum ErrorCode implements IError { FAILED_TO_PARSE_MALFORMED_LOG_RECORD(3117), ACTIVE_ENTITY_NOT_RUNNING(3118), REQUIRED_PARAM_IF_PARAM_IS_PRESENT(3119), + PARSER_DATA_PARSER_UNEXPECTED_TOKEN(3120), // Lifecycle management errors DUPLICATE_PARTITION_ID(4000), diff --git a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties index 345b9d8..18898bb 100644 --- a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties +++ b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties @@ -354,6 +354,7 @@ 3117 = Failed to parse record, malformed log record 3118 = Active Entity %1$s is not running (it is %2$s) 3119 = Parameter '%1$s' is required if '%2$s' is provided +3120 = Unexpected token %s: was expecting %s # Lifecycle management errors 4000 = Partition id %1$s for node %2$s already in use by node %3$s diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractJsonDataParser.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractJsonDataParser.java index a5d5a08..2bf0df4 100644 --- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractJsonDataParser.java +++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractJsonDataParser.java @@ -212,7 +212,7 @@ public abstract class AbstractJsonDataParser extends AbstractNestedDataParser<AD //fail fast if the current field is not nullable if (currentToken() == ADMToken.NULL && !isNullableType(fieldType)) { - throw new RuntimeDataException(ErrorCode.PARSER_TWEET_PARSER_CLOSED_FIELD_NULL, fieldName); + throw new RuntimeDataException(ErrorCode.PARSER_EXT_DATA_PARSER_CLOSED_FIELD_NULL, fieldName); } nullBitMap.set(fieldIndex); @@ -415,13 +415,18 @@ public abstract class AbstractJsonDataParser extends AbstractNestedDataParser<AD } } - protected HyracksDataException createException(IOException e) { + protected HyracksDataException createException(Exception e) { if (jsonParser != null) { String msg; if (e instanceof JsonParseException) { msg = ((JsonParseException) e).getOriginalMessage(); } else { - msg = ExceptionUtils.getRootCause(e).getMessage(); + Throwable rootCause = ExceptionUtils.getRootCause(e); + if (rootCause instanceof ParseException) { + msg = ((ParseException) rootCause).getOriginalMessage(); + } else { + msg = ExceptionUtils.getRootCause(e).getMessage(); + } } if (msg == null) { msg = ErrorCode.RECORD_READER_MALFORMED_INPUT_STREAM.errorMessage(); diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractNestedDataParser.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractNestedDataParser.java index c6f605d..eecbb19 100644 --- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractNestedDataParser.java +++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractNestedDataParser.java @@ -116,7 +116,7 @@ public abstract class AbstractNestedDataParser<T> extends AbstractDataParser { protected void checkOptionalConstraints(ARecordType recordType, BitSet nullBitmap) throws RuntimeDataException { for (int i = 0; i < recordType.getFieldTypes().length; i++) { if (!nullBitmap.get(i) && !isMissableType(recordType.getFieldTypes()[i])) { - throw new RuntimeDataException(ErrorCode.PARSER_TWEET_PARSER_CLOSED_FIELD_NULL, + throw new RuntimeDataException(ErrorCode.PARSER_EXT_DATA_PARSER_CLOSED_FIELD_NULL, recordType.getFieldNames()[i]); } } diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/JSONDataParser.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/JSONDataParser.java index b4ec46e..b2cffa9 100644 --- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/JSONDataParser.java +++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/JSONDataParser.java @@ -18,6 +18,8 @@ */ package org.apache.asterix.external.parser; +import static org.apache.asterix.common.exceptions.ErrorCode.PARSER_DATA_PARSER_UNEXPECTED_TOKEN; + import java.io.DataOutput; import java.io.IOException; import java.io.InputStream; @@ -76,7 +78,9 @@ public class JSONDataParser extends AbstractJsonDataParser implements IStreamDat //TODO(wyk): find a way to reset byte[] instead of creating a new parser for each record. jsonParser = jsonFactory.createParser(record.get(), 0, record.size()); geometryCoParser.reset(jsonParser); - nextToken(); + if (nextToken() != ADMToken.OBJECT_START) { + throw new ParseException(PARSER_DATA_PARSER_UNEXPECTED_TOKEN, currentToken(), ADMToken.OBJECT_START); + } parseObject(rootType, out); return true; } catch (IOException e) { diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/ParseException.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/ParseException.java index e9f93c9..f130fb3 100644 --- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/ParseException.java +++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/ParseException.java @@ -84,4 +84,8 @@ public class ParseException extends HyracksDataException { } return msg.append(": ").append(super.getMessage()).toString(); } + + public String getOriginalMessage() { + return super.getMessage(); + } } diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/TweetParser.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/TweetParser.java index 4726a50..b970b04 100644 --- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/TweetParser.java +++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/TweetParser.java @@ -199,7 +199,7 @@ public class TweetParser extends AbstractDataParser implements IRecordDataParser DataOutput fieldOutput = fieldValueBuffer.getDataOutput(); if (obj.get(curFNames[iter1]).isNull() && !(curTypes[iter1] instanceof AUnionType)) { if (curRecType.isClosedField(curFNames[iter1])) { - throw new RuntimeDataException(ErrorCode.PARSER_TWEET_PARSER_CLOSED_FIELD_NULL, + throw new RuntimeDataException(ErrorCode.PARSER_EXT_DATA_PARSER_CLOSED_FIELD_NULL, curFNames[iter1]); } else { continue; diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/ErrorMessageUtil.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/ErrorMessageUtil.java index 6479c8d..70b13fa 100644 --- a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/ErrorMessageUtil.java +++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/ErrorMessageUtil.java @@ -102,12 +102,15 @@ public class ErrorMessageUtil { try (Formatter fmt = new Formatter()) { if (!NONE.equals(component)) { fmt.format("%1$s%2$04d: ", component, errorCode); + + // if the message is already formatted, just return it + if (message.startsWith(fmt.toString())) { + return message; + } } - // if the message is already formatted, just return it - if (!fmt.toString().isEmpty() && message.startsWith(fmt.toString())) { - return message; + if (message != null) { + fmt.format(message, (Object[]) params); } - fmt.format(message == null ? "null" : message, (Object[]) params); if (sourceLoc != null) { fmt.out().append(" (in line ").append(String.valueOf(sourceLoc.getLine())).append(", at column ") .append(String.valueOf(sourceLoc.getColumn())).append(')');