diff --git a/src/clients/meta/MetaClient.cpp b/src/clients/meta/MetaClient.cpp index df4e3dc91f..27f7690c03 100644 --- a/src/clients/meta/MetaClient.cpp +++ b/src/clients/meta/MetaClient.cpp @@ -1714,7 +1714,15 @@ folly::Future> MetaClient::createEdgeSchema(GraphSpaceID spac getResponse( std::move(req), [](auto client, auto request) { return client->future_createEdge(request); }, - [](cpp2::ExecResp&& resp) -> EdgeType { return resp.get_id().get_edge_type(); }, + [](cpp2::ExecResp&& resp) -> EdgeType { + // Check if the creation was skipped due to IF NOT EXISTS + if (resp.skipped_ref() && resp.skipped_ref().value()) { + // Return a special value to indicate skipped creation + // Using -1 as a sentinel value for skipped creation + return -1; + } + return resp.get_id().get_edge_type(); + }, std::move(promise)); return future; } diff --git a/src/graph/executor/maintain/EdgeExecutor.cpp b/src/graph/executor/maintain/EdgeExecutor.cpp index d790e085f1..1052b46140 100644 --- a/src/graph/executor/maintain/EdgeExecutor.cpp +++ b/src/graph/executor/maintain/EdgeExecutor.cpp @@ -27,7 +27,33 @@ folly::Future CreateEdgeExecutor::execute() { << "' failed: " << resp.status(); return resp.status(); } - return Status::OK(); + + // Check if creation was skipped due to IF NOT EXISTS + if (resp.value() == -1) { + LOG(INFO) << "SpaceId: " << spaceId << ", Create edge `" << ceNode->getName() + << "' skipped: edge already exists"; + // Return a result with a message indicating the edge was skipped + DataSet result; + result.colNames = {"Result"}; + Row row; + row.values.emplace_back("Edge '" + ceNode->getName() + "' already exists, creation skipped"); + result.rows.emplace_back(std::move(row)); + return finish(ResultBuilder() + .value(Value(std::move(result))) + .iter(Iterator::Kind::kDefault) + .build()); + } + + // Edge was successfully created + DataSet result; + result.colNames = {"Result"}; + Row row; + row.values.emplace_back("Edge '" + ceNode->getName() + "' created successfully"); + result.rows.emplace_back(std::move(row)); + return finish(ResultBuilder() + .value(Value(std::move(result))) + .iter(Iterator::Kind::kDefault) + .build()); }); } diff --git a/src/interface/meta.thrift b/src/interface/meta.thrift index c452c68705..9e74d8ca17 100644 --- a/src/interface/meta.thrift +++ b/src/interface/meta.thrift @@ -207,6 +207,8 @@ struct ExecResp { 2: ID id, // Valid if ret equals E_LEADER_CHANGED. 3: common.HostAddr leader, + // Indicates if the operation was skipped due to IF NOT EXISTS + 4: optional bool skipped, } enum AlterSpaceOp { diff --git a/src/meta/processors/schema/CreateEdgeProcessor.cpp b/src/meta/processors/schema/CreateEdgeProcessor.cpp index c45a67b74e..cfcddb57b1 100644 --- a/src/meta/processors/schema/CreateEdgeProcessor.cpp +++ b/src/meta/processors/schema/CreateEdgeProcessor.cpp @@ -50,6 +50,8 @@ void CreateEdgeProcessor::process(const cpp2::CreateEdgeReq& req) { if (nebula::ok(ret)) { if (req.get_if_not_exists()) { handleErrorCode(nebula::cpp2::ErrorCode::SUCCEEDED); + resp_.skipped_ref() = true; // Indicate that the creation was skipped + LOG(INFO) << "Edge " << edgeName << " already exists, skipping creation due to IF NOT EXISTS"; } else { LOG(INFO) << "Create Edge Failed :" << edgeName << " has existed"; handleErrorCode(nebula::cpp2::ErrorCode::E_EXISTED); @@ -85,6 +87,7 @@ void CreateEdgeProcessor::process(const cpp2::CreateEdgeReq& req) { LOG(INFO) << "Create Edge " << edgeName << ", edgeType " << edgeType; resp_.id_ref() = to(edgeType, EntryType::EDGE); + resp_.skipped_ref() = false; // Indicate that the creation was not skipped auto timeInMilliSec = time::WallClock::fastNowInMilliSec(); LastUpdateTimeMan::update(data, timeInMilliSec); auto result = doSyncPut(std::move(data)); diff --git a/test_create_edge_enhancement.md b/test_create_edge_enhancement.md new file mode 100644 index 0000000000..d39377428d --- /dev/null +++ b/test_create_edge_enhancement.md @@ -0,0 +1,60 @@ +# CREATE EDGE IF NOT EXISTS Enhancement Test + +This document describes the expected behavior of the enhanced CREATE EDGE IF NOT EXISTS functionality. + +## Changes Made + +1. **Modified ExecResp structure** in `meta.thrift` to include an optional `skipped` boolean field +2. **Updated CreateEdgeProcessor** to set the `skipped` flag when edge creation is skipped due to IF NOT EXISTS +3. **Enhanced MetaClient::createEdgeSchema** to check the `skipped` flag and return -1 as a sentinel value when creation is skipped +4. **Improved CreateEdgeExecutor** to provide different user-friendly messages for created vs skipped edges + +## Expected Behavior + +### Before Enhancement +```sql +CREATE EDGE IF NOT EXISTS follow(degree int); +-- Result: "Execution succeeded" (even when the edge already exists) +``` + +### After Enhancement +```sql +-- First execution (edge doesn't exist) +CREATE EDGE IF NOT EXISTS follow(degree int); +-- Result: +-- +----------------------------------+ +-- | Result | +-- +----------------------------------+ +-- | Edge 'follow' created successfully | +-- +----------------------------------+ + +-- Second execution (edge already exists) +CREATE EDGE IF NOT EXISTS follow(degree int); +-- Result: +-- +------------------------------------------------+ +-- | Result | +-- +------------------------------------------------+ +-- | Edge 'follow' already exists, creation skipped | +-- +------------------------------------------------+ +``` + +## Technical Details + +- The `skipped` flag in `ExecResp` indicates whether an operation was skipped due to IF NOT EXISTS +- MetaClient returns -1 as a sentinel value when creation is skipped +- CreateEdgeExecutor provides different result messages based on the response value +- The enhancement maintains backward compatibility while providing clearer feedback to users + +## Testing Scenarios + +1. **Create new edge with IF NOT EXISTS** + - Should display "Edge 'name' created successfully" + +2. **Create existing edge with IF NOT EXISTS** + - Should display "Edge 'name' already exists, creation skipped" + +3. **Create existing edge without IF NOT EXISTS** + - Should fail with appropriate error message (existing behavior) + +4. **Create new edge without IF NOT EXISTS** + - Should display "Edge 'name' created successfully" \ No newline at end of file