From 6d58ed89b6645c74a853a0740c6e5551d278179c Mon Sep 17 00:00:00 2001 From: Shylock Hg <33566796+Shylock-Hg@users.noreply.github.com> Date: Thu, 30 Dec 2021 17:46:43 +0800 Subject: [PATCH] Support duration default value. --- src/meta/processors/schema/SchemaUtil.cpp | 290 +++++++++--------- src/meta/processors/schema/SchemaUtil.h | 7 + src/storage/test/GetNeighborsTest.cpp | 4 +- .../CreateDurationAsDefaultValue.feature | 23 ++ 4 files changed, 180 insertions(+), 144 deletions(-) create mode 100644 tests/tck/features/bugfix/CreateDurationAsDefaultValue.feature diff --git a/src/meta/processors/schema/SchemaUtil.cpp b/src/meta/processors/schema/SchemaUtil.cpp index 80568a8c523..b9a8937226e 100644 --- a/src/meta/processors/schema/SchemaUtil.cpp +++ b/src/meta/processors/schema/SchemaUtil.cpp @@ -5,7 +5,6 @@ #include "meta/processors/schema/SchemaUtil.h" -#include "common/base/ObjectPool.h" #include "common/expression/ConstantExpression.h" #include "common/time/TimeUtils.h" #include "common/utils/DefaultValueContext.h" @@ -38,152 +37,159 @@ bool SchemaUtil::checkType(std::vector& columns) { } continue; } - switch (column.get_type().get_type()) { - case PropertyType::BOOL: - if (!value.isBool()) { - LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " - << value.type(); - return false; - } - break; - case PropertyType::INT8: { - if (!value.isInt()) { - LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " - << value.type(); - return false; - } + if (!checkType(pool, name, column, value)) { + return false; + } + } + } + return true; +} - auto v = value.getInt(); - if (v > std::numeric_limits::max() || v < std::numeric_limits::min()) { - LOG(ERROR) << "`" << name << "' out of rang"; - return false; - } - break; - } - case PropertyType::INT16: { - if (!value.isInt()) { - LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " - << value.type(); - return false; - } +/*static*/ bool SchemaUtil::checkType(ObjectPool* pool, + const std::string& name, + cpp2::ColumnDef& column, + const Value& value) { + switch (column.get_type().get_type()) { + case PropertyType::BOOL: + if (!value.isBool()) { + LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " << value.type(); + return false; + } + return true; + case PropertyType::INT8: { + if (!value.isInt()) { + LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " << value.type(); + return false; + } - auto v = value.getInt(); - if (v > std::numeric_limits::max() || v < std::numeric_limits::min()) { - LOG(ERROR) << "`" << name << "' out of rang"; - return false; - } - break; - } - case PropertyType::INT32: { - if (!value.isInt()) { - LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " - << value.type(); - return false; - } + auto v = value.getInt(); + if (v > std::numeric_limits::max() || v < std::numeric_limits::min()) { + LOG(ERROR) << "`" << name << "' out of rang"; + return false; + } + return true; + } + case PropertyType::INT16: { + if (!value.isInt()) { + LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " << value.type(); + return false; + } - auto v = value.getInt(); - if (v > std::numeric_limits::max() || v < std::numeric_limits::min()) { - LOG(ERROR) << "`" << name << "' out of rang"; - return false; - } - break; - } - case PropertyType::INT64: - if (!value.isInt()) { - LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " - << value.type(); - return false; - } - break; - case PropertyType::FLOAT: - case PropertyType::DOUBLE: - if (!value.isFloat()) { - LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " - << value.type(); - return false; - } - break; - case PropertyType::STRING: - if (!value.isStr()) { - LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " - << value.type(); - return false; - } - break; - case PropertyType::FIXED_STRING: { - if (!value.isStr()) { - LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " - << value.type(); - return false; - } - auto& colType = column.get_type(); - size_t typeLen = colType.type_length_ref().value_or(0); - if (value.getStr().size() > typeLen) { - const auto trimStr = value.getStr().substr(0, typeLen); - value.setStr(trimStr); - const auto& fixedValue = *ConstantExpression::make(pool, value); - column.default_value_ref() = Expression::encode(fixedValue); - } - break; - } - case PropertyType::TIMESTAMP: { - if (!value.isInt()) { - LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " - << value.type(); - return false; - } - auto ret = time::TimeUtils::toTimestamp(value); - if (!ret.ok()) { - LOG(ERROR) << ret.status(); - return false; - } - break; - } - case PropertyType::DATE: - if (!value.isDate()) { - LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " - << value.type(); - return false; - } - break; - case PropertyType::TIME: - if (!value.isTime()) { - LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " - << value.type(); - return false; - } - break; - case PropertyType::DATETIME: - if (!value.isDateTime()) { - LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " - << value.type(); - return false; - } - break; - case PropertyType::GEOGRAPHY: { - if (!value.isGeography()) { // TODO(jie) - LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " - << value.type(); - return false; - } - meta::cpp2::GeoShape columnGeoShape = - column.get_type().geo_shape_ref().value_or(meta::cpp2::GeoShape::ANY); - GeoShape defaultExprGeoShape = value.getGeography().shape(); - if (columnGeoShape != meta::cpp2::GeoShape::ANY && - folly::to(columnGeoShape) != folly::to(defaultExprGeoShape)) { - LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " - << value.type() << ", geo shape is " << defaultExprGeoShape; - return false; - } - break; - } - default: - LOG(ERROR) << "Unsupported type"; - return false; + auto v = value.getInt(); + if (v > std::numeric_limits::max() || v < std::numeric_limits::min()) { + LOG(ERROR) << "`" << name << "' out of rang"; + return false; } + return true; } - } - return true; + case PropertyType::INT32: { + if (!value.isInt()) { + LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " << value.type(); + return false; + } + + auto v = value.getInt(); + if (v > std::numeric_limits::max() || v < std::numeric_limits::min()) { + LOG(ERROR) << "`" << name << "' out of rang"; + return false; + } + return true; + } + case PropertyType::INT64: + if (!value.isInt()) { + LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " << value.type(); + return false; + } + return true; + case PropertyType::FLOAT: + case PropertyType::DOUBLE: + if (!value.isFloat()) { + LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " << value.type(); + return false; + } + return true; + case PropertyType::STRING: + if (!value.isStr()) { + LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " << value.type(); + return false; + } + return true; + case PropertyType::FIXED_STRING: { + if (!value.isStr()) { + LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " << value.type(); + return false; + } + auto& colType = column.get_type(); + size_t typeLen = colType.type_length_ref().value_or(0); + if (value.getStr().size() > typeLen) { + const auto trimStr = value.getStr().substr(0, typeLen); + const auto& fixedValue = *ConstantExpression::make(pool, Value(trimStr)); + column.default_value_ref() = Expression::encode(fixedValue); + } + return true; + } + case PropertyType::TIMESTAMP: { + if (!value.isInt()) { + LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " << value.type(); + return false; + } + auto ret = time::TimeUtils::toTimestamp(value); + if (!ret.ok()) { + LOG(ERROR) << ret.status(); + return false; + } + return true; + } + case PropertyType::DATE: + if (!value.isDate()) { + LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " << value.type(); + return false; + } + return true; + case PropertyType::TIME: + if (!value.isTime()) { + LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " << value.type(); + return false; + } + return true; + case PropertyType::DATETIME: + if (!value.isDateTime()) { + LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " << value.type(); + return false; + } + return true; + case PropertyType::DURATION: + if (!value.isDuration()) { + LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " << value.type(); + return false; + } + return true; + case PropertyType::GEOGRAPHY: { + if (!value.isGeography()) { // TODO(jie) + LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " << value.type(); + return false; + } + meta::cpp2::GeoShape columnGeoShape = + column.get_type().geo_shape_ref().value_or(meta::cpp2::GeoShape::ANY); + GeoShape defaultExprGeoShape = value.getGeography().shape(); + if (columnGeoShape != meta::cpp2::GeoShape::ANY && + folly::to(columnGeoShape) != folly::to(defaultExprGeoShape)) { + LOG(ERROR) << "Invalid default value for ` " << name << "', value type is " << value.type() + << ", geo shape is " << defaultExprGeoShape; + return false; + } + return true; + } + case PropertyType::UNKNOWN: + case PropertyType::VID: + DLOG(ERROR) << "Don't supported type " + << apache::thrift::util::enumNameSafe(column.get_type().get_type()); + return false; + // no default so compiler will warning when lack + } // switch + DLOG(FATAL) << "Unknown property type " << static_cast(column.get_type().get_type()); + return false; } + } // namespace meta } // namespace nebula diff --git a/src/meta/processors/schema/SchemaUtil.h b/src/meta/processors/schema/SchemaUtil.h index 01e42ada49a..028ac370af7 100644 --- a/src/meta/processors/schema/SchemaUtil.h +++ b/src/meta/processors/schema/SchemaUtil.h @@ -6,6 +6,7 @@ #ifndef META_SCHEMAUTIL_H_ #define META_SCHEMAUTIL_H_ +#include "common/base/ObjectPool.h" #include "meta/processors/BaseProcessor.h" namespace nebula { @@ -17,6 +18,12 @@ class SchemaUtil final { public: static bool checkType(std::vector &columns); + + private: + static bool checkType(ObjectPool *pool, + const std::string &name, + cpp2::ColumnDef &column, + const Value &value); }; } // namespace meta diff --git a/src/storage/test/GetNeighborsTest.cpp b/src/storage/test/GetNeighborsTest.cpp index cd9c5eb6b9c..c3b560732aa 100644 --- a/src/storage/test/GetNeighborsTest.cpp +++ b/src/storage/test/GetNeighborsTest.cpp @@ -1119,8 +1119,8 @@ TEST(GetNeighborsTest, TtlTest) { LOG(INFO) << "colName: " << s; } ASSERT_EQ("Tim Duncan", (*resp.vertices_ref()).rows[0].values[0].getStr()); - ASSERT_TRUE((*resp.vertices_ref()).rows[0].values[1].empty()); // stat - ASSERT_TRUE((*resp.vertices_ref()).rows[0].values[2].empty()); // expr + ASSERT_TRUE((*resp.vertices_ref()).rows[0].values[1].empty()); // stat + ASSERT_TRUE((*resp.vertices_ref()).rows[0].values[2].empty()); // expr } FLAGS_mock_ttl_col = false; } diff --git a/tests/tck/features/bugfix/CreateDurationAsDefaultValue.feature b/tests/tck/features/bugfix/CreateDurationAsDefaultValue.feature new file mode 100644 index 00000000000..ebce8711481 --- /dev/null +++ b/tests/tck/features/bugfix/CreateDurationAsDefaultValue.feature @@ -0,0 +1,23 @@ +# Copyright (c) 2021 vesoft inc. All rights reserved. +# +# This source code is licensed under Apache 2.0 License. +Feature: Create duration as default value + + Scenario: Create duration as default value + Given an empty graph + And create a space with following options: + | partition_num | 9 | + | replica_factor | 1 | + | vid_type | FIXED_STRING(30) | + | charset | utf8 | + | collate | utf8_bin | + When executing query: + """ + create tag ddl_tag1(col1 DURATION DEFAULT duration({years: 3, months: 2})); + """ + Then the execution should be successful + When executing query: + """ + create edge ddl_edge1(col1 DURATION DEFAULT duration({years: 3, months: 2})); + """ + Then the execution should be successful