# Guide de démarrage rapide — Catrust

Catrust est une base de données qui comprend la **structure** de vos données.
Vous décrivez votre modèle en langage CQL, et Catrust gère les requêtes, les migrations
et les exports — sans SQL, sans ORM, sans configuration complexe.

Ce guide vous emmène de zéro à un Studio web fonctionnel **en moins de 5 minutes**.

---

## 1. Installation

### Option A — Docker (recommandé)

```bash
docker run -p 7878:7878 catrustdb/catrust:latest
```

### Option B — Binaire pré-compilé

Télécharger depuis [GitHub Releases](https://github.com/sirgudu/Catrust/releases) :
- Linux : `catrust-vX.Y.Z-x86_64-unknown-linux-gnu.tar.gz`
- macOS : `catrust-vX.Y.Z-aarch64-apple-darwin.tar.gz`
- Windows : `catrust-vX.Y.Z-x86_64-pc-windows-msvc.zip`

Extraire et placer `catrust` dans votre `PATH`.

> **Développeurs Rust** : vous pouvez aussi compiler depuis les sources (accès privé requis).

---

## 2. Lancer le Studio web

```bash
catrust serve --schema examples/company.cql
```

Le Studio s'ouvre automatiquement dans votre navigateur à `http://localhost:7878`.

Voici ce que vous pouvez faire depuis l'interface :
- Visualiser le schéma de votre base (graphe entités/relations)
- Exécuter des requêtes CQL
- Consulter l'historique des migrations
- Explorer les lineages de données

---

## 3. Votre premier schéma en 2 minutes

Créez un fichier `mon_projet.cql` :

```cql
schema Entreprise {
    entities
        Employe
        Departement

    foreign_keys
        travaille_dans : Employe -> Departement

    attributes
        nom     : Employe -> String
        salaire : Employe -> Integer
        budget  : Departement -> Integer
        libelle : Departement -> String
}
```

Chargez-le :

```bash
catrust serve --schema mon_projet.cql
```

Votre schéma est maintenant visible dans le Studio.

---

## 4. Insérer et interroger des données

Créez un fichier d'instance `mon_projet.cqli` :

```cqli
instance MonEquipe : Entreprise {
    generators
        d1 d2 : Departement
        e1 e2 e3 : Employe

    equations
        d1.libelle = "RD"       d1.budget = 120000
        d2.libelle = "Ventes"   d2.budget = 80000

        e1.nom = "Alice"   e1.salaire = 75000   e1.travaille_dans = d1
        e2.nom = "Bob"     e2.salaire = 60000   e2.travaille_dans = d1
        e3.nom = "Claire"  e3.salaire = 55000   e3.travaille_dans = d2
}
```

Requête SQL sur l'instance (via DataFusion) :

```bash
catrust query \
  --schema mon_projet.cql \
  --instance mon_projet.cqli \
  --sql 'SELECT * FROM "Employe" LIMIT 50'
```

Ou lancez le REPL interactif :

```bash
catrust query --schema mon_projet.cql --instance mon_projet.cqli --repl
```

---

## 5. Exporter vers SQL / CSV / Parquet

```bash
# PostgreSQL DDL (CREATE TABLE + FK)
catrust generate sql --schema mon_projet.cql --dialect postgres

# Snowflake
catrust generate sql --schema mon_projet.cql --dialect snowflake

# Cypher (Neo4j)
catrust generate cypher --schema mon_projet.cql

# Export Parquet (toutes les entités)
catrust export parquet --schema mon_projet.cql --instance mon_projet.cqli --output ./parquet/
```

---

## 6. Migrer un schéma (sans perte de données)

Catrust gère les migrations de façon **mathématiquement exacte** :
aucune donnée n'est perdue ou dupliquée lors d'un changement de modèle.

```bash
# Visualiser le plan de migration (sans appliquer)
catrust evolve \
  --from mon_projet.cql \
  --to mon_projet_v2.cql \
  --dry-run

# Appliquer la migration sur PostgreSQL
catrust evolve \
  --from mon_projet.cql \
  --to mon_projet_v2.cql \
  --url postgres://user:pass@localhost:5432/mabase

# CI/CD : échouer si la migration est destructive
catrust evolve \
  --from mon_projet.cql \
  --to mon_projet_v2.cql \
  --assert-safe
```

---

## 7. Sauvegarder et restaurer rapidement (format V2)

Pour les bases dépassant ~10 000 lignes, utilisez le format snapshot V2 :

```bash
# Snapshots : 93 ms pour 1 M lignes (13.5× plus rapide que le WAL)
catrust snapshot --schema mon_projet.cql --out mon_projet.v2

# Restaurer : ~5 ms pour 1 M lignes (~700× plus rapide)
catrust rollback --snapshot mon_projet.v2
```

En Rust, les index sont construits **à la demande** au premier filtre (lazy indexing) — pas à l'ouverture.

---

## 8. Lancer les tests

```bash
cargo test
```

> La suite de tests couvre l'ensemble des modules (0 failures). Consultez `TODO.md` pour l'état des tests.

---

## Annexe — API Rust

Les exemples suivants s'adressent aux développeurs qui intègrent Catrust
directement dans une application Rust.

### Votre premier programme Catrust

Voici un exemple minimal : définir un schéma, y insérer des données et exécuter une requête en mémoire.

```rust
use std::collections::HashMap;
use catrust::core::typeside::{BaseType, Value};
use catrust::core::schema::Schema;
use catrust::core::instance::Instance;
use catrust::core::query::*;
use catrust::core::eval;

fn main() {
    // 1. Définir le schéma (la "catégorie")
    let mut schema = Schema::new("Blog");
    schema
        .add_node("Article")
        .add_node("Auteur")
        .add_fk("ecrit_par", "Article", "Auteur")
        .add_attribute("titre",  "Article", BaseType::String)
        .add_attribute("vues",   "Article", BaseType::Integer)
        .add_attribute("pseudo", "Auteur",  BaseType::String);

    // 2. Peupler l'instance (le "foncteur")
    let mut inst = Instance::new("MonBlog", &schema);

    let alice = inst.insert("Auteur",
        HashMap::from([("pseudo".into(), Value::String("alice".into()))]),
        HashMap::new(),
    );
    inst.insert("Article",
        HashMap::from([
            ("titre".into(), Value::String("Intro à Rust".into())),
            ("vues".into(),  Value::Integer(1500)),
        ]),
        HashMap::from([("ecrit_par".into(), alice)]),
    );
    inst.insert("Article",
        HashMap::from([
            ("titre".into(), Value::String("CQL en pratique".into())),
            ("vues".into(),  Value::Integer(420)),
        ]),
        HashMap::from([("ecrit_par".into(), alice)]),
    );

    // 3. Requête : articles populaires d'alice (vues > 1000)
    let mut q = CqlQuery::new("ArticlesPopulaires", "Blog");
    q.add_block(QueryBlock {
        target_entity: "Résultat".into(),
        from_vars: HashMap::from([("a".into(), "Article".into())]),
        where_clauses: vec![
            WhereClause::Comparison {
                var: "a".into(),
                path: vec!["ecrit_par".into(), "pseudo".into()],
                op: CompOp::Eq,
                value: Value::String("alice".into()),
            },
            WhereClause::Comparison {
                var: "a".into(),
                path: vec!["vues".into()],
                op: CompOp::Gt,
                value: Value::Integer(1000),
            },
        ],
        attribute_bindings: HashMap::from([
            ("titre".into(), AttributeBinding {
                from_var: "a".into(), path: vec![], attribute: "titre".into(),
            }),
            ("vues".into(), AttributeBinding {
                from_var: "a".into(), path: vec![], attribute: "vues".into(),
            }),
        ]),
        fk_bindings: HashMap::new(),
    });

    let result = eval::eval_query(&q, &inst, &schema).unwrap();
    println!("{}", result);
    // → 1 ligne retournée : "Intro à Rust" (1500 vues)
}
```

---

## Exemple : migrer un schéma

```rust
use catrust::core::mapping::Mapping;
use catrust::core::schema::Path;
use catrust::core::migrate;

// Schéma source : Article --ecrit_par--> Auteur
// Schéma cible  : Post   --author-->    User

let mut mapping = Mapping::new("BlogMigration", "Blog", "NewBlog");
mapping
    .map_node("Article", "Post")
    .map_node("Auteur",  "User")
    .map_fk("ecrit_par", Path::new("Post", vec!["author"]))
    .map_attr_direct("titre",  "title")
    .map_attr_direct("vues",   "views")
    .map_attr_direct("pseudo", "username");

// Créer le schéma cible
let mut schema_new = Schema::new("NewBlog");
schema_new
    .add_node("Post")
    .add_node("User")
    .add_fk("author", "Post", "User")
    .add_attribute("title",    "Post", BaseType::String)
    .add_attribute("views",    "Post", BaseType::Integer)
    .add_attribute("username", "User", BaseType::String);

// Migration Σ : pousser les données vers le nouveau schéma
let instance_new = migrate::sigma(&mapping, &schema, &schema_new, &inst);
println!("{}", instance_new.display(&schema_new));
```

---

## Exemple : générer du SQL

```rust
use catrust::backend::sql::{SqlBackend, PostgresDialect};
use catrust::backend::Backend;

let backend = SqlBackend::new(PostgresDialect);

// DDL : CREATE TABLE
for stmt in backend.deploy_schema(&schema_new) {
    println!("{}", stmt);
}

// DML : INSERT INTO
for stmt in backend.export_instance(&schema_new, &instance_new) {
    println!("{}", stmt);
}
```

Sortie attendue :
```sql
CREATE TABLE "User" (
    "catrust_id" SERIAL PRIMARY KEY,
    "username" TEXT
);
CREATE TABLE "Post" (
    "catrust_id" SERIAL PRIMARY KEY,
    "title" TEXT,
    "views" INTEGER,
    "author_id" INTEGER REFERENCES "User"("catrust_id")
);
INSERT INTO "User" ("catrust_id", "username") VALUES (1, 'alice');
INSERT INTO "Post" ("catrust_id", "title", "views", "author_id") VALUES (1, 'Intro à Rust', 1500, 1);
```

---

## Étapes suivantes

- [Concepts catégoriques](./concepts.md) — comprendre la théorie derrière le moteur
- [Référence API](./api.md) — documentation de tous les modules
- [Guide backends](./backends.md) — PostgreSQL, Snowflake, Trino, Neo4j
