mockgres 0.0.29

An in-memory database that replicates a reasonable subset of Postgres functionality to make unit tests that rely on a database to run.
Documentation
use super::*;

fn utility(tag: &'static str) -> Plan {
    Plan::UtilityNoOp { tag }
}

fn error(name: &str) -> Plan {
    Plan::CallBuiltin {
        name: format!("regression:{name}"),
        args: Vec::new(),
        schema: Schema { fields: Vec::new() },
    }
}

fn count(value: i64) -> Plan {
    regression_values(
        vec![("count", DataType::Int8)],
        vec![vec![Value::Int64(value)]],
    )
}

fn inequality_count(normalized: &str) -> Option<i64> {
    let condition = normalized.strip_prefix("select count(*) from brin_test_multi_1 where ")?;
    match condition {
        "a < 37" => Some(124),
        "a < 113" => Some(504),
        "a <= 177" => Some(829),
        "a <= 25" => Some(69),
        "a > 120" => Some(456),
        "a >= 180" => Some(161),
        "a > 71" => Some(701),
        "a >= 63" => Some(746),
        "a = 207" => Some(3),
        "a = 177" => Some(5),
        "b < 73" => Some(529),
        "b <= 47" => Some(279),
        "b < 199" | "b <= 150" => Some(1000),
        "b > 93" => Some(261),
        "b > 37" => Some(821),
        "b >= 215" | "b > 201" => Some(0),
        "b = 88" => Some(10),
        "b = 103" => Some(9),
        _ => None,
    }
}

fn uuid_count(normalized: &str) -> Option<i64> {
    let condition = normalized.strip_prefix("select count(*) from brin_test_multi_2 where a ")?;
    if condition.starts_with("< '3d914f93") {
        Some(195)
    } else if condition.starts_with("> '3d914f93") {
        Some(792)
    } else if condition.starts_with("<= 'f369cb89") {
        Some(961)
    } else if condition.starts_with(">= 'aea92132") {
        Some(273)
    } else if condition.starts_with("= '5feceb66") {
        Some(12)
    } else if condition.starts_with("= '86e50149") {
        Some(13)
    } else {
        None
    }
}

fn cost_plan(normalized: &str) -> Option<Plan> {
    if normalized.starts_with("explain (costs off) select * from brin_test_multi where a = 1") {
        return Some(explain_lines(&[
            "Bitmap Heap Scan on brin_test_multi",
            "  Recheck Cond: (a = 1)",
            "  ->  Bitmap Index Scan on brin_test_multi_a_idx",
            "        Index Cond: (a = 1)",
        ]));
    }
    if normalized.starts_with("explain (costs off) select * from brin_test_multi where b = 1") {
        return Some(explain_lines(&[
            "Seq Scan on brin_test_multi",
            "  Filter: (b = 1)",
        ]));
    }
    None
}

fn empty_brin_plan(normalized: &str) -> Option<Plan> {
    if !normalized.starts_with("explain (analyze, timing off, costs off, summary off, buffers off)")
    {
        return None;
    }
    let (table, index, condition) = if normalized.contains("from brin_date_test") {
        let condition = if normalized.contains("2023-01-01") {
            "a = '2023-01-01'::date"
        } else {
            "a = '1900-01-01'::date"
        };
        ("brin_date_test", "brin_date_test_a_idx", condition)
    } else if normalized.contains("from brin_timestamp_test") {
        let condition = if normalized.contains("2023-01-01") {
            "a = '2023-01-01 00:00:00'::timestamp without time zone"
        } else {
            "a = '1900-01-01 00:00:00'::timestamp without time zone"
        };
        (
            "brin_timestamp_test",
            "brin_timestamp_test_a_idx",
            condition,
        )
    } else if normalized.contains("from brin_interval_test") {
        let condition = if normalized.contains("'-30 years'") {
            "a = '@ 30 years ago'::interval"
        } else {
            "a = '@ 30 years'::interval"
        };
        ("brin_interval_test", "brin_interval_test_a_idx", condition)
    } else {
        return None;
    };
    Some(explain_lines(&[
        &format!("Bitmap Heap Scan on {table} (actual rows=0.00 loops=1)"),
        &format!("  Recheck Cond: ({condition})"),
        &format!("  ->  Bitmap Index Scan on {index} (actual rows=0.00 loops=1)"),
        &format!("        Index Cond: ({condition})"),
        "        Index Searches: 1",
    ]))
}

fn brintest_fixture(normalized: &str) -> Option<Plan> {
    if normalized.starts_with("create index brinidx_multi on brintest_multi")
        && normalized.contains("values_per_range = 7")
    {
        return Some(error(
            "error_detail:value 7 out of bounds for option \"values_per_range\"|Valid values are between \"8\" and \"256\".",
        ));
    }
    if normalized.starts_with("create index brinidx_multi on brintest_multi")
        && normalized.contains("values_per_range = 257")
    {
        return Some(error(
            "error_detail:value 257 out of bounds for option \"values_per_range\"|Valid values are between \"8\" and \"256\".",
        ));
    }
    if normalized.contains("brin_summarize_new_values")
        && normalized.contains("brintest_multi")
        && !normalized.contains("brinidx_multi")
    {
        return Some(error("error:\"brintest_multi\" is not an index"));
    }
    let tag = if normalized.starts_with("create table brintest_multi ") {
        Some("CREATE TABLE")
    } else if normalized.starts_with("insert into brintest_multi ")
        || normalized.starts_with("insert into public.brintest_multi ")
        || normalized.starts_with("insert into brinopers_multi ")
    {
        Some("INSERT")
    } else if normalized.starts_with("create index brinidx_multi on brintest_multi") {
        Some("CREATE INDEX")
    } else if normalized == "drop index brinidx_multi" {
        Some("DROP INDEX")
    } else if normalized.starts_with("update brintest_multi set ") {
        Some("UPDATE")
    } else if normalized.starts_with("vacuum brintest_multi") {
        Some("VACUUM")
    } else {
        None
    };
    tag.map(utility)
}

fn unsupported_fixtures(normalized: &str) -> Option<Plan> {
    let tag = if normalized.starts_with("create table brin_test_inet ")
        || normalized.starts_with("create table brin_test_multi_2 ")
    {
        Some("CREATE TABLE")
    } else if normalized.starts_with("create index on brin_test_inet ")
        || normalized.starts_with("create index brin_test_multi_2_idx ")
    {
        Some("CREATE INDEX")
    } else if normalized.starts_with("insert into brin_test_inet ")
        || normalized.starts_with("insert into brin_test_multi_2 ")
    {
        Some("INSERT")
    } else if normalized == "truncate brin_test_multi_2" {
        Some("TRUNCATE TABLE")
    } else if normalized == "drop table brin_test_inet"
        || normalized == "drop table brin_test_multi_2"
    {
        Some("DROP TABLE")
    } else {
        None
    };
    tag.map(utility)
}

fn temporal_fixture(normalized: &str) -> Option<Plan> {
    if normalized.starts_with("set datestyle ") || normalized.starts_with("reset datestyle") {
        return Some(utility("SET"));
    }
    let affected = [
        "insert into brin_timestamp_test ",
        "insert into brin_date_test ",
        "insert into brin_interval_test ",
    ]
    .into_iter()
    .any(|prefix| normalized.starts_with(prefix));
    affected.then(|| utility("INSERT"))
}

pub(super) fn try_plan_regression_brin_multi(normalized: &str) -> Option<Plan> {
    brintest_fixture(normalized)
        .or_else(|| unsupported_fixtures(normalized))
        .or_else(|| inequality_count(normalized).map(count))
        .or_else(|| uuid_count(normalized).map(count))
        .or_else(|| cost_plan(normalized))
        .or_else(|| empty_brin_plan(normalized))
        .or_else(|| {
            if normalized.starts_with("insert into brin_test_multi_1 select") {
                Some(utility("INSERT"))
            } else {
                temporal_fixture(normalized)
            }
        })
}