dbase 0.5.0

Read & Write .dbf in Rust
Documentation
use datafusion::error::Result;
use datafusion::execution::context::SessionState;
use datafusion::execution::runtime_env::{RuntimeConfig, RuntimeEnv};
use datafusion::prelude::*;
use dbase::{DbaseTable, DbaseTableFactory};
use std::sync::Arc;

#[tokio::main]
async fn main() -> Result<()> {
    // create local execution context
    let cfg = RuntimeConfig::new();
    let env = RuntimeEnv::new(cfg).unwrap();
    let ses = SessionConfig::new();
    let mut state = SessionState::with_config_rt(ses, Arc::new(env));

    // add DbaseTableFactory to support "create external table stored as dbase" syntax
    state
        .table_factories_mut()
        .insert("DBASE".to_string(), Arc::new(DbaseTableFactory {}));
    let ctx = SessionContext::with_state(state);

    // register DBF file as external table
    let sql = "create external table stations stored as dbase location './tests/data/stations.dbf'";
    ctx.sql(sql).await.unwrap();

    // execute the query
    let df = ctx
        .sql(
            "
        select *
        from stations
        where line='blue'
            and name like 'F%'",
        )
        .await?;

    df.show().await?;

    // alternatively, we can manually create and register the table
    let stations_table = DbaseTable::new("./tests/data/stations.dbf");
    ctx.register_table("stations2", Arc::new(stations_table))
        .expect("failed to register table");

    // self join as a simple example
    let df2 = ctx
        .sql(
            "
        select s1.name, s1.line as line_1, s2.line as line_2
        from stations s1
        join stations2 s2
            on s1.name = s2.name",
        )
        .await?;
    // print the results
    df2.show().await?;

    // can then call df.write_csv(), df.write_parquet(), etc.

    Ok(())
}