uqa-engine 0.4.0

Engine: schema-aware table store, catalog restore, transactions
//
// Unified Query Algebra
//
// Copyright (c) 2023-2026 Cognica, Inc.
//

//! Domain catalog publication must preserve independent concurrent declarations.

use crate::tests::relation_lock_support::{before_commit, error, reopen, sessions, sql};
use uqa_core::Value;

mod constraint_identities;
mod type_names;

#[test]
fn domains_with_matching_constraint_names_commit_independently() {
    for provider in 0..3 {
        let (directory, first, second) = sessions(provider);
        sql(
            &first,
            "BEGIN; CREATE DOMAIN a AS int CONSTRAINT shared CHECK(VALUE>0)",
        );
        let second = before_commit(
            &first,
            second,
            "CREATE DOMAIN b AS int CONSTRAINT shared CHECK(VALUE<100)",
        );
        sql(&first, "SELECT 1::a, 1::b");
        drop(second);
        drop(first);
        let restored = reopen(provider, &directory.path().join("table-locks.db"));
        sql(&restored, "SELECT 1::a, 1::b");
    }
}

#[test]
fn independent_domain_creations_and_deletions_commit_without_lost_records() {
    for provider in 0..3 {
        for (holder, worker, expected) in [
            ("DROP DOMAIN a", "CREATE DOMAIN c AS int", vec!["b", "c"]),
            ("CREATE DOMAIN c AS int", "DROP DOMAIN a", vec!["b", "c"]),
            ("DROP DOMAIN a", "DROP DOMAIN b", vec![]),
        ] {
            let (directory, first, second) = sessions(provider);
            sql(&first, "CREATE DOMAIN a AS int; CREATE DOMAIN b AS int");
            sql(&first, &format!("BEGIN; {holder}"));
            let second = before_commit(&first, second, worker);
            let names = |engine: &crate::Engine| {
                sql(
                    engine,
                    "SELECT typname FROM pg_type WHERE typtype='d' AND typnamespace=(SELECT oid FROM pg_namespace WHERE nspname='public') ORDER BY typname",
                )
                .rows
                .into_iter()
                .map(|row| row["typname"].clone())
                .collect::<Vec<_>>()
            };
            let expected = expected
                .into_iter()
                .map(|name| Value::Str(name.into()))
                .collect::<Vec<_>>();
            assert_eq!(names(&first), expected);
            assert_eq!(names(&second), expected);
            drop((first, second));
            let restored = reopen(provider, &directory.path().join("table-locks.db"));
            assert_eq!(names(&restored), expected);
        }
    }
}

#[test]
fn private_domain_records_survive_peer_publication_and_undo_at_each_isolation() {
    for provider in 0..3 {
        for isolation in ["READ COMMITTED", "REPEATABLE READ", "SERIALIZABLE"] {
            for finish in ["COMMIT", "ROLLBACK", "ROLLBACK TO changes; COMMIT"] {
                let (directory, first, second) = sessions(provider);
                sql(&first, "CREATE DOMAIN removed AS int");
                sql(&first, &format!("BEGIN ISOLATION LEVEL {isolation}; SELECT * FROM t; SAVEPOINT changes; DROP DOMAIN removed; CREATE DOMAIN private AS int CONSTRAINT shared CHECK(VALUE>0)"));
                let private = first.durable.domains.read()["public.private"].object_id;
                sql(&second, "CREATE DOMAIN peer AS int CONSTRAINT shared CHECK(VALUE<100); INSERT INTO t VALUES(2)");
                first.list_named_analyzers().unwrap();
                if isolation == "READ COMMITTED" {
                    sql(&first, "SELECT typname FROM pg_type");
                }
                let registry = first.durable.domains.snapshot();
                assert_eq!(registry["public.private"].object_id, private);
                assert!(
                    registry.contains_key("public.peer"),
                    "{provider}/{isolation}/{finish}"
                );
                assert!(!registry.contains_key("public.removed"));
                assert_eq!(
                    sql(&first, "SELECT count(*) AS n FROM t").rows[0]["n"],
                    Value::Int(if isolation == "READ COMMITTED" { 2 } else { 1 })
                );
                sql(&first, finish);
                sql(&first, "SELECT 1::peer");
                drop((first, second));
                let restored = reopen(provider, &directory.path().join("table-locks.db"));
                let registry = restored.durable.domains.read();
                assert!(registry.contains_key("public.peer"));
                assert_eq!(registry.contains_key("public.private"), finish == "COMMIT");
                assert_eq!(registry.contains_key("public.removed"), finish != "COMMIT");
                if finish == "COMMIT" {
                    assert_eq!(registry["public.private"].object_id, private);
                }
            }
        }
    }
}

#[test]
fn domain_cascade_preserves_constraint_ownership_and_undo_across_reopen() {
    for provider in 0..3 {
        for removal in [
            "DROP DOMAIN removed.d CASCADE",
            "DROP SCHEMA removed CASCADE",
        ] {
            let (directory, engine, peer) = sessions(provider);
            drop(peer);
            sql(&engine, "CREATE SCHEMA removed; CREATE DOMAIN removed.d AS int; CREATE TABLE domain_keys(id removed.d PRIMARY KEY, u removed.d UNIQUE, keep int, twice int GENERATED ALWAYS AS (id::int * 2) STORED); CREATE TABLE domain_ref(id int REFERENCES domain_keys(id)); CREATE VIEW domain_view AS SELECT twice FROM domain_keys; CREATE INDEX domain_plain ON domain_keys(id); CREATE INDEX domain_expression ON domain_keys(((keep::removed.d)::int)); CREATE INDEX domain_predicate ON domain_keys(keep) WHERE (keep::removed.d)::int > 0; CREATE INDEX domain_keep ON domain_keys(keep); INSERT INTO domain_keys(id,u,keep) VALUES (2,4,3); INSERT INTO domain_ref VALUES (2)");
            let indexes = |engine: &crate::Engine| {
                sql(engine, "SELECT indexname FROM pg_indexes WHERE tablename='domain_keys' ORDER BY indexname").rows
            };
            let original = indexes(&engine);
            assert_eq!(original.len(), 6);
            error(&engine, "DROP INDEX domain_keys_pkey CASCADE", "2BP01");
            error(&engine, "DROP DOMAIN removed.d", "2BP01");
            sql(&engine, &format!("BEGIN; SAVEPOINT kept; {removal}"));
            assert_eq!(indexes(&engine).len(), 1);
            assert_eq!(sql(&engine, "SELECT * FROM domain_keys").columns, ["keep"]);
            sql(&engine, "ROLLBACK TO kept; COMMIT");
            drop(engine);
            let path = directory.path().join("table-locks.db");
            let engine = reopen(provider, &path);
            assert_eq!(indexes(&engine), original);
            assert_eq!(
                sql(&engine, "SELECT twice FROM domain_view").rows[0]["twice"],
                Value::Int(4)
            );
            error(&engine, "INSERT INTO domain_ref VALUES (9)", "23503");
            sql(&engine, removal);
            drop(engine);
            let engine = reopen(provider, &path);
            let rows = indexes(&engine);
            assert_eq!(rows.len(), 1);
            assert_eq!(rows[0]["indexname"], Value::Str("domain_keep".into()));
            let rows = sql(&engine, "SELECT * FROM domain_keys");
            assert_eq!(rows.columns, ["keep"]);
            assert_eq!(rows.rows[0]["keep"], Value::Int(3));
            sql(&engine, "INSERT INTO domain_ref VALUES (9)");
            error(&engine, "SELECT * FROM domain_view", "42P01");
        }
    }
}