switchy_database 0.5.0

Switchy database package
#![cfg(all(feature = "sqlite-sqlx", feature = "schema"))]

use std::sync::Arc;
use switchy_database::{
    Database, DatabaseValue,
    schema::{Column, DataType},
    sqlx::sqlite::SqliteSqlxDatabase,
};

#[tokio::test]
async fn string_defaults_are_data() {
    check("items", "value", DataType::Text).await;
}

#[cfg(not(feature = "raw-sql"))]
#[tokio::test]
async fn schema_names_are_exact_identifiers() {
    check(
        "items.dot\"; --",
        "column.dot\" DEFAULT 9 --",
        DataType::Custom("TEXT); DROP TABLE sentinel; --".into()),
    )
    .await;
}

async fn check(table: &str, column: &str, data_type: DataType) {
    let pool = sqlx::sqlite::SqlitePoolOptions::new()
        .max_connections(1)
        .connect("sqlite::memory:")
        .await
        .unwrap();
    let db = SqliteSqlxDatabase::new(Arc::new(switchy_async::sync::Mutex::new(pool)));
    let default = "é'); DROP TABLE sentinel; --";
    db.create_table(table)
        .column(Column {
            name: "id".into(),
            data_type: DataType::BigInt,
            nullable: false,
            auto_increment: false,
            default: None,
        })
        .column(Column {
            name: column.into(),
            data_type,
            nullable: false,
            auto_increment: false,
            default: Some(DatabaseValue::String(default.into())),
        })
        .execute(&db)
        .await
        .unwrap();
    assert!(db.table_exists(table).await.unwrap());
    let row = db.insert(table).value("id", 1).execute(&db).await.unwrap();
    assert_eq!(row.get(column), Some(DatabaseValue::String(default.into())));
    let explicit = "漢字'); DROP TABLE sentinel; --";
    let row = db
        .insert(table)
        .value("id", 2)
        .value(column, explicit)
        .execute(&db)
        .await
        .unwrap();
    assert_eq!(
        row.get(column),
        Some(DatabaseValue::String(explicit.into()))
    );
    db.close().await.unwrap();
}