Gunnar

nordisk/skade

.nornir/for-idiots.md

# skade — for idiots (f0)

> **Class:** `idiot` · **Function axis:** `f0` (zero → running, the whole thing).
> No prior knowledge assumed. Every step spelled out. For the plain-English
> arrow-58 build story see [`arrow58-for-dummies.md`](arrow58-for-dummies.md);
> for a gentle worked tour see [`dummy-guide.md`](dummy-guide.md).

## What is this thing?

An **Iceberg catalog** is the little notebook that remembers *which file is the
current version of each table* in a data warehouse. Normally that notebook is a
whole separate server (a JVM service, a database). **skade-katalog** is that
notebook squeezed into **one file on disk** that your program opens directly — no
server to run, no network. One folder on your computer becomes a complete
"lakehouse": the notebook file plus the data files it points at.

The name: Skaði is the Norse winter queen. She keeps the icebergs in order.

## Step 0 — what you need

1. A computer with **Rust** installed. Open a terminal and type:

   ```
   rustc --version
   ```

   Press Enter. If it prints a version, you're good. If it says "command not
   found", install Rust from https://rustup.rs first.

## Step 1 — make a project

In your terminal, type these lines, pressing Enter after each:

```
cargo new my-lakehouse
cd my-lakehouse
```

## Step 2 — add the ingredients

Open the file called `Cargo.toml` in a text editor. Find the line that says
`[dependencies]` and, on the lines right under it, type:

```toml
skade-katalog = "0.1"
iceberg = { package = "iceberg-arrow58", version = "0.9.1" }
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
anyhow = "1"
```

Save the file.

## Step 3 — write the program

Open the file `src/main.rs`. Delete everything in it. Type this in:

```rust
use std::sync::Arc;
use iceberg::{Catalog, CatalogBuilder, NamespaceIdent};
use iceberg::io::LocalFsStorageFactory;
use skade_katalog::RedbCatalogBuilder;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Open (or create) the one-file catalog.
    let catalog = RedbCatalogBuilder::default()
        .db_path("warehouse/catalog.redb")
        .warehouse_location("file:///tmp/my-lakehouse/warehouse")
        .with_storage_factory(Arc::new(LocalFsStorageFactory))
        .load("demo", Default::default())
        .await?;

    // Make a "namespace" (a folder for tables) called `sales`.
    let ns = NamespaceIdent::from_strs(["sales"])?;
    if !catalog.namespace_exists(&ns).await? {
        catalog.create_namespace(&ns, Default::default()).await?;
    }

    // Ask the catalog what namespaces it knows about, and print them.
    for n in catalog.list_namespaces(None).await? {
        println!("namespace: {n:?}");
    }
    println!("It worked. Your catalog is the file warehouse/catalog.redb");
    Ok(())
}
```

Save it.

## Step 4 — run it

Back in the terminal, type:

```
cargo run
```

Press Enter. The first time, it downloads and compiles the ingredients (this can
take a few minutes — that's normal). When it finishes you'll see:

```
namespace: NamespaceIdent(["sales"])
It worked. Your catalog is the file warehouse/catalog.redb
```

## Step 5 — see what you made

Type:

```
ls warehouse
```

You'll see `catalog.redb`. **That one file is your entire catalog.** Copy that
folder anywhere and you've copied your whole lakehouse. There is no server running
in the background — when your program stops, nothing is left running.

## What just happened

- You opened a catalog that lives in a single file.
- You made a namespace and listed it back.
- Everything happened inside your own program — no database server, no Java, no
  network.

From here, the next thing to learn is making **tables** and reading them back —
that's in the [guide](guide.md). If a word here confused you, the
[dummy-guide](dummy-guide.md) walks through the same ideas more slowly.