Skip to content

atopio/surrealex

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

55 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Surrealex

Dead simple SurrealDB query generator.

A Rust library for building SurrealQL queries with a fluent, type-safe API.

🌟 Features

  • Fluent builder API with compile-time state checking
  • Type-safe field selection using the fields! macro
  • Complex WHERE conditions and graph traversal support
  • Support for SELECT, FROM, WHERE, FETCH, ORDER BY, LIMIT, and START AT
  • Full DELETE statement support with ONLY, RETURN, TIMEOUT, and EXPLAIN clauses

πŸ“¦ Installation

Add to your Cargo.toml:

[dependencies]
surrealex = { version = "0.1.0", features = ["macros"] }

Or from Git:

[dependencies]
surrealex = { git = "https://github.com/MordechaiHadad/surrealex", features = ["macros"] }

πŸ”§ Usage

Basic Query

use surrealex::QueryBuilder;

let query = QueryBuilder::select(surrealex::fields!("id", "name"))
    .from("users")
    .r#where("age > 18")
    .order_by("created_at", Sort::Desc)
    .limit(10)
    .build();

assert_eq!(query, "SELECT id, name FROM users WHERE age > 18 ORDER BY created_at DESC LIMIT 10");

Complex WHERE Conditions

use surrealex::enums::Condition;

let query = QueryBuilder::select(surrealex::fields!("id"))
    .from("users")
    .r#where(
        Condition::new("age > 18")
        .and(Condition::new("status = 'active'").or("status = 'pending'"))
    )
    .build();

assert_eq!(
    query,
    "SELECT id FROM users WHERE (age > 18 AND (status = 'active' OR status = 'pending'))"
);

Graph Traversal

use surrealex::types::select::GraphTraversalParams;

let query = QueryBuilder::select(surrealex::fields!(*))
    .graph_traverse(
        GraphTraversalParams::start_out("friends")
            .step_in("posts")
            .fields(surrealex::fields!(*))
            .alias("friend_posts"),
    )
    .from("user")
    .build();

assert_eq!(
    query,
    "SELECT *, ->friends<-posts.* AS friend_posts FROM user"
);

Versioning API (with_version)

QueryBuilder::select(...) uses SurrealV2 by default.
You can target a specific SurrealDB version with QueryBuilder::with_version(...).

use surrealex::{QueryBuilder, SurrealV1};
use surrealex::enums::SelectionFields;

let query = QueryBuilder::with_version(SurrealV1)
    .select(SelectionFields::All)
    .graph_traverse(
        surrealex::types::select::GraphTraversalParams::start_out("friends")
            .step_in("posts")
            .fields(surrealex::fields!("title", "created_at"))
            .alias("friend_posts"),
    )
    .from("user")
    .build();

assert_eq!(
    query,
    "SELECT *, ->friends<-posts.title, ->friends<-posts.created_at AS friend_posts FROM user"
);

SurrealV2 and SurrealV3 use object destructuring for graph traversal field selection:

use surrealex::{QueryBuilder, SurrealV3};
use surrealex::enums::SelectionFields;
use surrealex::types::select::GraphTraversalParams;

let query = QueryBuilder::with_version(SurrealV3)
    .select(SelectionFields::All)
    .graph_traverse(
        GraphTraversalParams::start_out("friends")
            .step_in("posts")
            .fields(surrealex::fields!("title", "created_at"))
            .alias("friend_posts"),
    )
    .from("user")
    .build();

assert_eq!(
    query,
    "SELECT *, ->friends<-posts.{title, created_at} AS friend_posts FROM user"
);

Delete Statement

use surrealex::QueryBuilder;

// Basic delete
let query = QueryBuilder::delete("users")
    .r#where("active = false")
    .build();

assert_eq!(query, "DELETE FROM users WHERE active = false");

DELETE ONLY with RETURN

When using ONLY, SurrealDB expects a single-result RETURN clause. The builder generates the query and leaves validation to the server.

use surrealex::QueryBuilder;

let query = QueryBuilder::delete("person:one")
    .only()
    .return_before()
    .build();

assert_eq!(query, "DELETE ONLY person:one RETURN BEFORE");

RETURN Variants

use surrealex::QueryBuilder;

// RETURN NONE / BEFORE / AFTER / DIFF
let query = QueryBuilder::delete("users")
    .r#where("expired = true")
    .return_diff()
    .build();

assert_eq!(query, "DELETE FROM users WHERE expired = true RETURN DIFF");

// RETURN specific fields
let query = QueryBuilder::delete("users")
    .return_params(vec!["$before", "$after"])
    .build();

assert_eq!(query, "DELETE FROM users RETURN $before, $after");

TIMEOUT and EXPLAIN

use surrealex::QueryBuilder;

let query = QueryBuilder::delete("logs")
    .r#where("created_at < '2024-01-01'")
    .return_none()
    .timeout("5s")
    .explain_full()
    .build();

assert_eq!(
    query,
    "DELETE FROM logs WHERE created_at < '2024-01-01' RETURN NONE TIMEOUT 5s EXPLAIN FULL"
);

πŸ“ License

This project is open source. See the repository for license details.

πŸ”— Links

About

Dead simple SurrealDB query generator.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages