Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/clients/meta/MetaClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1714,7 +1714,15 @@ folly::Future<StatusOr<EdgeType>> 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;
}
Expand Down
28 changes: 27 additions & 1 deletion src/graph/executor/maintain/EdgeExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,33 @@ folly::Future<Status> 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());
});
}

Expand Down
2 changes: 2 additions & 0 deletions src/interface/meta.thrift
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
3 changes: 3 additions & 0 deletions src/meta/processors/schema/CreateEdgeProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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));
Expand Down
60 changes: 60 additions & 0 deletions test_create_edge_enhancement.md
Original file line number Diff line number Diff line change
@@ -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"