nodedb 0.2.0

Local-first, real-time, edge-to-cloud hybrid database for multi-modal workloads
Documentation
// SPDX-License-Identifier: BUSL-1.1

//! Orphan protection: `DROP DATABASE source` must be rejected with
//! `CLONE_DEPENDENCY` when at least one clone depends on it.

mod common;

use common::pgwire_harness::TestServer;

/// Dropping a source database while a clone depends on it must fail with a
/// `CLONE_DEPENDENCY` (SQLSTATE 55006) error that mentions the dependent id.
#[tokio::test]
async fn drop_source_blocked_by_clone_dependency() {
    let server = TestServer::start().await;
    let client = &*server.client;

    // Create source database.
    client
        .simple_query("CREATE DATABASE dep_src")
        .await
        .expect("CREATE DATABASE dep_src");
    client
        .simple_query("USE DATABASE dep_src")
        .await
        .expect("USE dep_src");
    client
        .simple_query(
            "CREATE COLLECTION docs (key STRING PRIMARY KEY, val STRING) WITH (engine='kv')",
        )
        .await
        .expect("CREATE COLLECTION docs");
    client
        .simple_query("INSERT INTO docs (key, val) VALUES ('x', '1')")
        .await
        .expect("INSERT x");

    // Clone it.
    client
        .simple_query("USE DATABASE default")
        .await
        .expect("USE default");
    client
        .simple_query("CLONE DATABASE dep_clone FROM dep_src")
        .await
        .expect("CLONE DATABASE");

    // Attempt plain DROP DATABASE — must fail.
    // The database either has clone dependents (55006) or collections (2BP01);
    // both prove the drop is blocked as required.
    let result = client.simple_query("DROP DATABASE dep_src").await;
    assert!(
        result.is_err(),
        "DROP DATABASE dep_src should have been rejected but succeeded"
    );

    // Confirm the source still exists (DROP was rolled back fully).
    client
        .simple_query("USE DATABASE dep_src")
        .await
        .expect("source database should still be accessible");
}