diff --git a/dataset/csv-error-tests/union-no-conversion.csv b/dataset/csv-error-tests/union-no-conversion.csv new file mode 100644 index 0000000000..f6e83621eb --- /dev/null +++ b/dataset/csv-error-tests/union-no-conversion.csv @@ -0,0 +1,2 @@ +"col:UNION(u UINT8, s INT8)" +a diff --git a/src/binder/bind/bind_create_macro.cpp b/src/binder/bind/bind_create_macro.cpp index 3a382fd40b..4347655f26 100644 --- a/src/binder/bind/bind_create_macro.cpp +++ b/src/binder/bind/bind_create_macro.cpp @@ -2,6 +2,7 @@ #include "binder/bound_create_macro.h" #include "common/exception/binder.h" #include "common/string_format.h" +#include "common/string_utils.h" #include "parser/create_macro.h" using namespace kuzu::common; @@ -13,6 +14,7 @@ namespace binder { std::unique_ptr Binder::bindCreateMacro(const Statement& statement) { auto& createMacro = reinterpret_cast(statement); auto macroName = createMacro.getMacroName(); + StringUtils::toUpper(macroName); if (catalog.getReadOnlyVersion()->containMacro(macroName)) { throw BinderException{stringFormat("Macro {} already exists.", macroName)}; } @@ -23,7 +25,7 @@ std::unique_ptr Binder::bindCreateMacro(const Statement& stateme auto scalarMacro = std::make_unique(createMacro.getMacroExpression()->copy(), createMacro.getPositionalArgs(), std::move(defaultArgs)); - return std::make_unique(macroName, std::move(scalarMacro)); + return std::make_unique(std::move(macroName), std::move(scalarMacro)); } } // namespace binder diff --git a/src/binder/bind/bind_file_scan.cpp b/src/binder/bind/bind_file_scan.cpp index 5a372561a9..dd62831434 100644 --- a/src/binder/bind/bind_file_scan.cpp +++ b/src/binder/bind/bind_file_scan.cpp @@ -46,9 +46,6 @@ std::vector Binder::bindFilePaths(const std::vector& f boundFilePaths.insert( boundFilePaths.end(), globbedFilePaths.begin(), globbedFilePaths.end()); } - if (boundFilePaths.empty()) { - throw BinderException{stringFormat("Invalid file path: {}.", filePaths[0])}; - } return boundFilePaths; } diff --git a/src/binder/bind/bind_graph_pattern.cpp b/src/binder/bind/bind_graph_pattern.cpp index 7c7a837288..dbb167e2ec 100644 --- a/src/binder/bind/bind_graph_pattern.cpp +++ b/src/binder/bind/bind_graph_pattern.cpp @@ -186,9 +186,10 @@ static std::unique_ptr createPropertyExpression(const std::string& p } for (auto type : propertyDataTypes) { if (*propertyDataTypes[0] != *type) { - stringFormat("Expected the same data type for property {} but found {} and {}.", - propertyName, LogicalTypeUtils::dataTypeToString(*type), - LogicalTypeUtils::dataTypeToString(*propertyDataTypes[0])); + throw BinderException( + stringFormat("Expected the same data type for property {} but found {} and {}.", + propertyName, LogicalTypeUtils::dataTypeToString(*type), + LogicalTypeUtils::dataTypeToString(*propertyDataTypes[0]))); } } return make_unique(*propertyDataTypes[0], propertyName, uniqueVariableName, diff --git a/src/catalog/catalog_content.cpp b/src/catalog/catalog_content.cpp index 827e0d6a4c..e1955b51b3 100644 --- a/src/catalog/catalog_content.cpp +++ b/src/catalog/catalog_content.cpp @@ -230,10 +230,12 @@ std::unique_ptr CatalogContent::copy() const { void CatalogContent::validateStorageVersion(storage_version_t savedStorageVersion) { auto storageVersion = StorageVersionInfo::getStorageVersion(); if (savedStorageVersion != storageVersion) { + // LCOV_EXCL_START throw RuntimeException( stringFormat("Trying to read a database file with a different version. " "Database file version: {}, Current build storage version: {}", savedStorageVersion, storageVersion)); + // LCOV_EXCL_END } } diff --git a/src/catalog/table_schema.cpp b/src/catalog/table_schema.cpp index 576e7807da..ed49238347 100644 --- a/src/catalog/table_schema.cpp +++ b/src/catalog/table_schema.cpp @@ -30,24 +30,16 @@ std::vector TableSchema::getProperties() const { return propertiesToReturn; } -std::string TableSchema::getPropertyName(property_id_t propertyID) const { - for (auto& property : properties) { - if (property->getPropertyID() == propertyID) { - return property->getName(); - } - } - throw RuntimeException(stringFormat( - "Table: {} doesn't have a property with propertyID={}.", tableName, propertyID)); -} - property_id_t TableSchema::getPropertyID(const std::string& propertyName) const { for (auto& property : properties) { if (property->getName() == propertyName) { return property->getPropertyID(); } } + // LCOV_EXCL_START throw RuntimeException(stringFormat( "Table: {} doesn't have a property with propertyName={}.", tableName, propertyName)); + // LCOV_EXCL_END } // TODO(Guodong): Instead of looping over properties, cache a map between propertyID and columnID. @@ -66,8 +58,10 @@ Property* TableSchema::getProperty(property_id_t propertyID) const { return property.get(); } } + // LCOV_EXCL_START throw RuntimeException(stringFormat( "Table: {} doesn't have a property with propertyID={}.", tableName, propertyID)); + // LCOV_EXCL_END } void TableSchema::renameProperty(property_id_t propertyID, const std::string& newName) { @@ -77,7 +71,9 @@ void TableSchema::renameProperty(property_id_t propertyID, const std::string& ne return; } } + // LCOV_EXCL_START throw InternalException(stringFormat("Property with id={} not found.", propertyID)); + // LCOV_EXCL_END } void TableSchema::serialize(FileInfo* fileInfo, uint64_t& offset) { @@ -118,7 +114,9 @@ std::unique_ptr TableSchema::deserialize(FileInfo* fileInfo, uint64 result = RdfGraphSchema::deserialize(fileInfo, offset); } break; default: { + // LCOV_EXCL_START throw NotImplementedException{"TableSchema::deserialize"}; + // LCOV_EXCL_END } } result->tableName = tableName; diff --git a/src/common/assert.cpp b/src/common/assert.cpp index f7753f918f..799ba0e52f 100644 --- a/src/common/assert.cpp +++ b/src/common/assert.cpp @@ -8,11 +8,12 @@ namespace kuzu { namespace common { void kuAssertInternal(bool condition, const char* condition_name, const char* file, int linenr) { - if (condition) { - return; + if (!condition) { + // LCOV_EXCL_START + throw InternalException(stringFormat( + "Assertion triggered in file \"{}\" on line {}: {}", file, linenr, condition_name)); + // LCOV_EXCL_END } - throw InternalException(stringFormat( - "Assertion triggered in file \"{}\" on line {}: {}", file, linenr, condition_name)); } } // namespace common diff --git a/src/common/file_utils.cpp b/src/common/file_utils.cpp index 3bb1cec9a6..7aa5ce1aa5 100644 --- a/src/common/file_utils.cpp +++ b/src/common/file_utils.cpp @@ -4,6 +4,7 @@ #include "common/exception/storage.h" #include "common/string_format.h" +#include "common/system_message.h" #include "glob/glob.hpp" #ifdef _WIN32 @@ -32,13 +33,14 @@ int64_t FileInfo::getFileSize() { if (!GetFileSizeEx((HANDLE)handle, &size)) { auto error = GetLastError(); throw StorageException(stringFormat("Cannot read size of file. path: {} - Error {}: {}", - path, error, std::system_category().message(error))); + path, error, systemErrMessage(error))); } return size.QuadPart; #else struct stat s; if (fstat(fd, &s) == -1) { - return -1; + throw StorageException(stringFormat( + "Cannot read size of file. path: {} - Error {}: {}", path, errno, posixErrMessage())); } return s.st_size; #endif @@ -99,10 +101,6 @@ std::unique_ptr FileUtils::openFile( void FileUtils::writeToFile( FileInfo* fileInfo, const uint8_t* buffer, uint64_t numBytes, uint64_t offset) { - auto fileSize = fileInfo->getFileSize(); - if (fileSize == -1) { - throw Exception(stringFormat("File {} not open.", fileInfo->path)); - } uint64_t remainingNumBytesToWrite = numBytes; uint64_t bufferOffset = 0; // Split large writes to 1GB at a time @@ -128,10 +126,13 @@ void FileUtils::writeToFile( uint64_t numBytesWritten = pwrite(fileInfo->fd, buffer + bufferOffset, numBytesToWrite, offset); if (numBytesWritten != numBytesToWrite) { + // LCOV_EXCL_START throw Exception( stringFormat("Cannot write to file. path: {} fileDescriptor: {} offsetToWrite: {} " - "numBytesToWrite: {} numBytesWritten: {}.", - fileInfo->path, fileInfo->fd, offset, numBytesToWrite, numBytesWritten)); + "numBytesToWrite: {} numBytesWritten: {}. Error: {}", + fileInfo->path, fileInfo->fd, offset, numBytesToWrite, numBytesWritten, + posixErrMessage())); + // LCOV_EXCL_END } #endif remainingNumBytesToWrite -= numBytesWritten; @@ -146,8 +147,10 @@ void FileUtils::copyFile( return; std::error_code errorCode; if (!std::filesystem::copy_file(from, to, options, errorCode)) { + // LCOV_EXCL_START throw Exception(stringFormat( "Error copying file {} to {}. ErrorMessage: {}", from, to, errorCode.message())); + // LCOV_EXCL_END } } @@ -180,9 +183,11 @@ void FileUtils::readFromFile( #else auto numBytesRead = pread(fileInfo->fd, buffer, numBytes, position); if (numBytesRead != numBytes && fileInfo->getFileSize() != position + numBytesRead) { + // LCOV_EXCL_START throw Exception(stringFormat("Cannot read from file: {} fileDescriptor: {} " "numBytesRead: {} numBytesToRead: {} position: {}", fileInfo->path, fileInfo->fd, numBytesRead, numBytes, position)); + // LCOV_EXCL_END } #endif } @@ -190,14 +195,20 @@ void FileUtils::readFromFile( void FileUtils::createDir(const std::string& dir) { try { if (std::filesystem::exists(dir)) { + // LCOV_EXCL_START throw Exception(stringFormat("Directory {} already exists.", dir)); + // LCOV_EXCL_END } if (!std::filesystem::create_directory(dir)) { + // LCOV_EXCL_START throw Exception(stringFormat( "Directory {} cannot be created. Check if it exists and remove it.", dir)); + // LCOV_EXCL_END } } catch (std::exception& e) { + // LCOV_EXCL_START throw Exception(stringFormat("Failed to create directory {} due to: {}", dir, e.what())); + // LCOV_EXCL_END } } @@ -212,8 +223,10 @@ void FileUtils::removeDir(const std::string& dir) { if (!fileOrPathExists(dir)) return; if (!std::filesystem::remove_all(dir, removeErrorCode)) { + // LCOV_EXCL_START throw Exception(stringFormat( - "Error removing directory {}. Error Message: {}", dir, removeErrorCode.message())); + "Error removing directory {}. Error Message: {}", dir, removeErrorCode.message())); + // LCOV_EXCL_END } } @@ -224,8 +237,10 @@ void FileUtils::renameFileIfExists(const std::string& oldName, const std::string std::error_code errorCode; std::filesystem::rename(oldName, newName, errorCode); if (errorCode.value() != 0) { + // LCOV_EXCL_START throw Exception(stringFormat("Error replacing file {} to {}. ErrorMessage: {}", oldName, newName, errorCode.message())); + // LCOV_EXCL_END } } @@ -233,8 +248,10 @@ void FileUtils::removeFileIfExists(const std::string& path) { if (!fileOrPathExists(path)) return; if (remove(path.c_str()) != 0) { - throw Exception( - stringFormat("Error removing directory or file {}. Error Message: ", path)); + // LCOV_EXCL_START + throw Exception(stringFormat( + "Error removing directory or file {}. Error Message: {}", path, posixErrMessage())); + // LCOV_EXCL_END } } @@ -268,7 +285,12 @@ void FileUtils::truncateFileToSize(FileInfo* fileInfo, uint64_t size) { std::system_category().message(error))); } #else - ftruncate(fileInfo->fd, size); + if (ftruncate(fileInfo->fd, size) < 0) { + // LCOV_EXCL_START + throw Exception( + stringFormat("Failed to truncate file {}: {}", fileInfo->path, posixErrMessage())); + // LCOV_EXCL_END + } #endif } diff --git a/src/common/types/blob.cpp b/src/common/types/blob.cpp index 0c992a23de..8901c1add5 100644 --- a/src/common/types/blob.cpp +++ b/src/common/types/blob.cpp @@ -58,9 +58,10 @@ uint64_t Blob::fromString(const char* str, uint64_t length, uint8_t* resultBuffe } else if (str[i] <= 127) { resultBuffer[resultPos++] = str[i]; } else { - throw ConversionException( - "Invalid byte encountered in STRING -> BLOB conversion. All non-ascii characters " - "must be escaped with hex codes (e.g. \\xAA)"); + // LCOV_EXCL_START + throw InternalException("Invalid byte encountered in STRING -> BLOB conversion that " + "should have been caught during getBlobSize"); + // LCOV_EXCL_END } } return resultPos; @@ -89,7 +90,7 @@ void Blob::validateHexCode(const uint8_t* blobStr, uint64_t length, uint64_t cur if (curPos + HexFormatConstants::LENGTH > length) { throw ConversionException( "Invalid hex escape code encountered in string -> blob conversion: " - "unterminated escape code at end of blob"); + "unterminated escape code at end of string"); } if (memcmp(blobStr + curPos, HexFormatConstants::PREFIX, HexFormatConstants::PREFIX_LENGTH) != 0 || diff --git a/src/function/base_lower_upper_operation.cpp b/src/function/base_lower_upper_operation.cpp index ef5f409b44..2d1248c610 100644 --- a/src/function/base_lower_upper_operation.cpp +++ b/src/function/base_lower_upper_operation.cpp @@ -18,10 +18,12 @@ uint32_t BaseLowerUpperFunction::getResultLen(char* inputStr, uint32_t inputLen, int size = 0; int codepoint = utf8proc_codepoint(inputStr + i, size); if (codepoint < 0) { + // LCOV_EXCL_START // TODO(Xiyang): We shouldn't allow invalid UTF-8 to enter a string column. std::string funcName = isUpper ? "UPPER" : "LOWER"; throw RuntimeException( common::stringFormat("Failed calling {}: Invalid UTF-8.", funcName)); + // LCOV_EXCL_END } int convertedCodepoint = isUpper ? utf8proc_toupper(codepoint) : utf8proc_tolower(codepoint); diff --git a/src/function/vector_path_functions.cpp b/src/function/vector_path_functions.cpp index 1a55ba322a..34dcf4ab8f 100644 --- a/src/function/vector_path_functions.cpp +++ b/src/function/vector_path_functions.cpp @@ -55,7 +55,7 @@ std::unique_ptr PropertiesVectorFunction::bindFunc( const binder::expression_vector& arguments, FunctionDefinition* definition) { if (arguments[1]->expressionType != ExpressionType::LITERAL) { throw BinderException(stringFormat( - "Expect literal input as the second argument for {}().", PROPERTIES_FUNC_NAME)); + "Expected literal input as the second argument for {}().", PROPERTIES_FUNC_NAME)); } auto key = ((binder::LiteralExpression&)*arguments[1]).getValue()->getValue(); auto listType = arguments[0]->getDataType(); diff --git a/src/include/catalog/table_schema.h b/src/include/catalog/table_schema.h index 3bbeea9bcf..5914d4218a 100644 --- a/src/include/catalog/table_schema.h +++ b/src/include/catalog/table_schema.h @@ -62,8 +62,6 @@ class TableSchema { std::move(propertyName), std::move(dataType), increaseNextPropertyID(), tableID)); } - std::string getPropertyName(common::property_id_t propertyID) const; - common::property_id_t getPropertyID(const std::string& propertyName) const; common::column_id_t getColumnID(common::property_id_t propertyID) const; diff --git a/src/processor/map/expression_mapper.cpp b/src/processor/map/expression_mapper.cpp index 0dc41dabc3..141e1f07de 100644 --- a/src/processor/map/expression_mapper.cpp +++ b/src/processor/map/expression_mapper.cpp @@ -68,8 +68,10 @@ std::unique_ptr ExpressionMapper::getEvaluator( } else if (canEvaluateAsFunction(expressionType)) { return getFunctionEvaluator(expression, schema); } else { + // LCOV_EXCL_START throw NotImplementedException(stringFormat( "Cannot evaluate expression with type {}.", expressionTypeToString(expressionType))); + // LCOV_EXCL_END } } @@ -84,8 +86,10 @@ std::unique_ptr ExpressionMapper::getConstantEvaluator( } else if (canEvaluateAsFunction(expressionType)) { return getFunctionEvaluator(expression, nullptr); } else { + // LCOV_EXCL_START throw NotImplementedException(stringFormat( "Cannot evaluate expression with type {}.", expressionTypeToString(expressionType))); + // LCOV_EXCL_END } } diff --git a/src/processor/operator/persistent/reader/csv/driver.cpp b/src/processor/operator/persistent/reader/csv/driver.cpp index 5238940d5e..60281ec71f 100644 --- a/src/processor/operator/persistent/reader/csv/driver.cpp +++ b/src/processor/operator/persistent/reader/csv/driver.cpp @@ -586,7 +586,8 @@ void copyStringToVector(ValueVector* vector, uint64_t rowToAdd, std::string_view } } if (selectedFieldIdx == INVALID_STRUCT_FIELD_IDX) { - throw ParserException{stringFormat("No parsing rule matches value: {}.", strVal)}; + throw ConversionException{stringFormat("Could not convert to union type {}: {}.", + LogicalTypeUtils::dataTypeToString(type), strVal)}; } StructVector::getFieldVector(vector, UnionType::TAG_FIELD_IDX) ->setValue(rowToAdd, selectedFieldIdx); diff --git a/src/storage/in_mem_storage_structure/in_mem_lists.cpp b/src/storage/in_mem_storage_structure/in_mem_lists.cpp index f17ef17ac6..c971da77ff 100644 --- a/src/storage/in_mem_storage_structure/in_mem_lists.cpp +++ b/src/storage/in_mem_storage_structure/in_mem_lists.cpp @@ -88,7 +88,7 @@ void InMemLists::copyArrowArray(arrow::Array* boundNodeOffsets, arrow::Array* po } break; // TODO(Ziyi): Add support of VAR_LIST and more native parquet data types. default: { - throw CopyException("Unsupported data type "); + throw CopyException("Unsupported data type"); } } } diff --git a/src/storage/storage_info.cpp b/src/storage/storage_info.cpp index 1b0a8a9428..05576bca26 100644 --- a/src/storage/storage_info.cpp +++ b/src/storage/storage_info.cpp @@ -11,8 +11,10 @@ namespace storage { storage_version_t StorageVersionInfo::getStorageVersion() { auto storageVersionInfo = getStorageVersionInfo(); if (!storageVersionInfo.contains(KUZU_STORAGE_VERSION)) { + // LCOV_EXCL_START throw RuntimeException( stringFormat("Invalid storage version name: {}", KUZU_STORAGE_VERSION)); + // LCOV_EXCL_END } return storageVersionInfo.at(KUZU_STORAGE_VERSION); } diff --git a/src/storage/storage_structure/disk_array.cpp b/src/storage/storage_structure/disk_array.cpp index 7a232050bd..5fe2a9839d 100644 --- a/src/storage/storage_structure/disk_array.cpp +++ b/src/storage/storage_structure/disk_array.cpp @@ -75,9 +75,11 @@ template void BaseDiskArray::checkOutOfBoundAccess(TransactionType trxType, uint64_t idx) { auto currentNumElements = getNumElementsNoLock(trxType); if (idx >= currentNumElements) { + // LCOV_EXCL_START throw RuntimeException(stringFormat( "idx: {} of the DiskArray to be accessed is >= numElements in DiskArray{}.", idx, currentNumElements)); + // LCOV_EXCL_END } } diff --git a/test/c_api/query_result_test.cpp b/test/c_api/query_result_test.cpp index f45d760ba0..712c522f86 100644 --- a/test/c_api/query_result_test.cpp +++ b/test/c_api/query_result_test.cpp @@ -30,6 +30,16 @@ TEST_F(CApiQueryResultTest, GetErrorMessage) { free(errorMessage); } +TEST_F(CApiQueryResultTest, ToString) { + auto connection = getConnection(); + auto result = kuzu_connection_query(connection, "MATCH (a:person) RETURN COUNT(*)"); + ASSERT_TRUE(kuzu_query_result_is_success(result)); + auto str_repr = kuzu_query_result_to_string(result); + ASSERT_NE(str_repr, nullptr); + free(str_repr); + kuzu_query_result_destroy(result); +} + TEST_F(CApiQueryResultTest, GetNumColumns) { auto connection = getConnection(); auto result = diff --git a/test/test_files/csv/errors.test b/test/test_files/csv/errors.test index 078a2d6a30..ad3bfb2ba4 100644 --- a/test/test_files/csv/errors.test +++ b/test/test_files/csv/errors.test @@ -8,7 +8,6 @@ ---- error Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/csv-error-tests/escape-then-eof.csv on line 2: escape at end of file. --CASE Errors -STATEMENT LOAD FROM "${KUZU_ROOT_DIRECTORY}/dataset/csv-error-tests/quote-then-eof.csv" RETURN COUNT(*); ---- error Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/csv-error-tests/quote-then-eof.csv on line 2: unterminated quotes. @@ -28,3 +27,7 @@ Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/csv-error-tests/too -STATEMENT LOAD FROM "${KUZU_ROOT_DIRECTORY}/dataset/csv-error-tests/too-many-values.csv" RETURN COUNT(*); ---- error Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/csv-error-tests/too-many-values.csv, on line 2: expected 1 values per row, but got more. + +-STATEMENT LOAD FROM "${KUZU_ROOT_DIRECTORY}/dataset/csv-error-tests/union-no-conversion.csv" (HEADER=TRUE) RETURN * +---- error +Conversion exception: Could not convert to union type UNION(u:UINT8, s:INT8): a. diff --git a/test/test_files/exceptions/binder/empty_db_binder_error.test b/test/test_files/exceptions/binder/empty_db_binder_error.test index d0e17a7cbc..670741de35 100644 --- a/test/test_files/exceptions/binder/empty_db_binder_error.test +++ b/test/test_files/exceptions/binder/empty_db_binder_error.test @@ -7,3 +7,59 @@ -STATEMENT MATCH () WITH NULL AS a RETURN a; ---- error Binder exception: No node table exists in database. + +-CASE DuplicateMacro +-STATEMENT CREATE MACRO inc(x) AS x + 1 +---- ok +-STATEMENT CREATE MACRO INC(x, y) AS x + y +---- error +Binder exception: Macro INC already exists. + +-CASE WrongNumOfNumpyFiles +-STATEMENT CREATE NODE TABLE temp(ID INT64, PRIMARY KEY(ID)); +---- ok +-STATEMENT COPY temp FROM ("${KUZU_ROOT_DIRECTORY}/dataset/npy-20k/id_int64.npy", "${KUZU_ROOT_DIRECTORY}/dataset/npy-20k/two_dim_float.npy") BY COLUMN; +---- error +Binder exception: Number of columns mismatch. Expected 1 but got 2. + +-CASE DropNodeReferencedByRel +-STATEMENT CREATE NODE TABLE person(ID INT64, PRIMARY KEY(ID)) +---- ok +-STATEMENT CREATE REL TABLE follows(FROM person TO person) +---- ok +-STATEMENT DROP TABLE person +---- error +Binder exception: Cannot delete node table person referenced by rel table follows. + +-CASE MismatchedPropertyDataTypes +-STATEMENT CREATE NODE TABLE person(ID INT64, PRIMARY KEY(ID)) +---- ok +-STATEMENT CREATE NODE TABLE fruit(ID STRING, PRIMARY KEY(ID)) +---- ok +-STATEMENT MATCH (pf:person:fruit) RETURN *; +---- error +Binder exception: Expected the same data type for property ID but found STRING and INT64. + +-CASE UnsupportedRecursiveRelProjectionItem +-STATEMENT CREATE NODE TABLE person(ID INT64, PRIMARY KEY(ID)) +---- ok +-STATEMENT CREATE REL TABLE follows(FROM person TO person) +---- ok +-STATEMENT MATCH (p:person)-[:follows* SHORTEST (r, n | {r}, {n})]-(q:person) RETURN *; +---- error +Binder exception: Unsupported projection item n on recursive rel. + +-CASE PathPropertiesErrors +-STATEMENT CREATE NODE TABLE person(ID STRING, PRIMARY KEY(ID)) +---- ok +-STATEMENT CREATE REL TABLE follows(FROM person TO person) +---- ok +-STATEMENT MATCH path = (p:person)-[:follows* SHORTEST]-(q:person) RETURN properties(nodes(path), p.ID) +---- error +Binder exception: Expected literal input as the second argument for PROPERTIES(). +-STATEMENT MATCH path = (p:person)-[:follows* SHORTEST]-(q:person) RETURN properties(nodes(path), "abc") +---- error +Binder exception: Invalid property name: abc. +-STATEMENT MATCH path = (p:person)-[:follows* SHORTEST]-(q:person) RETURN properties([], "abc") +---- error +Binder exception: Cannot extract properties from INT64[]. diff --git a/test/test_files/tinysnb/cast/cast_error.test b/test/test_files/tinysnb/cast/cast_error.test index 0a43706d64..0ee6ef8e49 100644 --- a/test/test_files/tinysnb/cast/cast_error.test +++ b/test/test_files/tinysnb/cast/cast_error.test @@ -248,3 +248,24 @@ Conversion exception: Value fasdf is not a valid boolean -STATEMENT RETURN TO_BOOL("fal"); ---- error Conversion exception: Value fal is not a valid boolean + +-CASE SerialOutOfRange +-STATEMENT RETURN TO_SERIAL(TO_UINT64(9223372036854775807) * TO_UINT64(2)); +---- error +Runtime exception: Value 18446744073709551614 is not within INT64 range + +-CASE NonAsciiStringToBlob +-STATEMENT RETURN BLOB('😀') +---- error +Conversion exception: Invalid byte encountered in STRING -> BLOB conversion. All non-ascii characters must be escaped with hex codes (e.g. \xAA) + +-CASE StringToBlobInvalidHexCode +-STATEMENT RETURN BLOB('\\xgg') +---- error +Conversion exception: Invalid hex escape code encountered in string -> blob conversion: \xgg + +-CASE StringToBlobUnterminatedHexCode +-STATEMENT RETURN BLOB('\\xa') +---- error +Conversion exception: Invalid hex escape code encountered in string -> blob conversion: unterminated escape code at end of string +