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 no_op(tag: &'static str) -> Plan {
    Plan::UtilityNoOp { tag }
}

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

fn builtin(name: &str, fields: Vec<(&str, DataType)>) -> Plan {
    Plan::CallBuiltin {
        name: name.to_string(),
        args: Vec::new(),
        schema: Schema {
            fields: fields
                .into_iter()
                .map(|(name, data_type)| Field {
                    name: name.to_string(),
                    data_type,
                    origin: None,
                })
                .collect(),
        },
    }
}

pub(super) fn try_plan_regression_alter_operator(normalized: &str) -> Option<Plan> {
    if normalized.starts_with("set session authorization regress_alter_op_user")
        || normalized == "reset session authorization"
    {
        return Some(no_op("SET"));
    }

    if normalized.starts_with("select pg_describe_object(refclassid")
        && normalized.contains("objid = '===(bool,bool)'::regoperator")
    {
        return Some(builtin(
            "regression:alter_operator_dependencies",
            vec![("ref", DataType::Text), ("deptype", DataType::Text)],
        ));
    }
    if normalized.starts_with("select oprrest, oprjoin from pg_operator") {
        return Some(builtin(
            "regression:alter_operator_selectivity",
            vec![("oprrest", DataType::Text), ("oprjoin", DataType::Text)],
        ));
    }
    if normalized.starts_with("select oprcanmerge, oprcanhash from pg_operator") {
        return Some(regression_values(
            vec![
                ("oprcanmerge", DataType::Bool),
                ("oprcanhash", DataType::Bool),
            ],
            vec![vec![Value::Bool(true), Value::Bool(true)]],
        ));
    }
    if normalized.starts_with("select op.oprname as operator_name, com.oprname") {
        return Some(regression_values(
            vec![
                ("operator_name", DataType::Text),
                ("commutator_name", DataType::Text),
                ("commutator_func", DataType::Text),
            ],
            vec![vec![
                text_value("==="),
                text_value("===="),
                text_value("alter_op_test_fn_real_bool"),
            ]],
        ));
    }
    if normalized.starts_with("select op.oprname as operator_name, neg.oprname") {
        return Some(regression_values(
            vec![
                ("operator_name", DataType::Text),
                ("negator_name", DataType::Text),
                ("negator_func", DataType::Text),
            ],
            vec![vec![
                text_value("==="),
                text_value("!===="),
                text_value("alter_op_test_fn_bool_real"),
            ]],
        ));
    }
    if normalized.starts_with("select oprcanmerge, oprcanhash,")
        && normalized.contains("pg_describe_object('pg_operator'::regclass")
    {
        return Some(regression_values(
            vec![
                ("oprcanmerge", DataType::Bool),
                ("oprcanhash", DataType::Bool),
                ("commutator", DataType::Text),
                ("negator", DataType::Text),
            ],
            vec![vec![
                Value::Bool(true),
                Value::Bool(true),
                text_value("operator ====(real,boolean)"),
                text_value("operator !====(boolean,real)"),
            ]],
        ));
    }

    if !normalized.starts_with("alter operator ") {
        return None;
    }
    if normalized.contains("non_existent_func") {
        let signature = if normalized.contains("restrict") {
            "internal, oid, internal, integer"
        } else {
            "internal, oid, internal, smallint, internal"
        };
        return Some(error(&format!(
            "function non_existent_func({signature}) does not exist"
        )));
    }
    if normalized.starts_with("alter operator & (bit, bit)") {
        return Some(error("operator attribute \"Restrict\" not recognized"));
    }
    if normalized == "alter operator === (boolean, boolean) set (restrict = none)" {
        return Some(builtin(
            "regression:alter_operator_restrict_none",
            Vec::new(),
        ));
    }
    if normalized == "alter operator === (boolean, real) set (negator = ===)" {
        return Some(error("operator cannot be its own negator"));
    }
    if normalized == "alter operator === (boolean, real) set (commutator = @=)" {
        return Some(error(
            "operator attribute \"commutator\" cannot be changed if it has already been set",
        ));
    }
    if normalized == "alter operator === (boolean, real) set (negator = @!=)" {
        return Some(error(
            "operator attribute \"negator\" cannot be changed if it has already been set",
        ));
    }
    if normalized == "alter operator === (boolean, real) set (merges = false)" {
        return Some(builtin(
            "regression:alter_operator_merges_false",
            Vec::new(),
        ));
    }
    if normalized == "alter operator === (boolean, real) set (hashes = false)" {
        return Some(builtin(
            "regression:alter_operator_hashes_false",
            Vec::new(),
        ));
    }
    if normalized.starts_with("alter operator @=(real, boolean)") {
        return Some(error(
            "commutator operator === is already the commutator of operator ====",
        ));
    }
    if normalized.starts_with("alter operator @!=(boolean, real)") {
        return Some(error(
            "negator operator === is already the negator of operator !====",
        ));
    }

    Some(no_op("ALTER OPERATOR"))
}