Skip to content

Commit

Permalink
feat: book
Browse files Browse the repository at this point in the history
  • Loading branch information
Fyko committed Sep 28, 2023
1 parent 76a5961 commit 7aec298
Show file tree
Hide file tree
Showing 15 changed files with 319 additions and 2 deletions.
49 changes: 49 additions & 0 deletions .github/workflows/book.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Deploy Book

on:
push:
branches: [main]
paths:
- 'book/**'

concurrency:
group: "pages"
cancel-in-progress: false

jobs:
build:
name: Build Website
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Install mdbook
uses: taiki-e/install-action@mdbook

- name: Setup Pages
id: pages
uses: actions/configure-pages@v3

- name: Run Clippy
working-directory: book
run: mdbook build

- name: Upload Pages Artifact
uses: actions/upload-pages-artifact
with:
path: book/book

deploy:
needs: build
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ version = "0.1.8-alpha"
license = "MIT OR Apache-2.0"
edition = "2021"
repository = "https://github.com/trufflehq/scyllax"
keywords = ["scylla", "cassandra", "orm", "sqlx", "trufflehq", "truffle", "youtube", "twitch"]
keywords = ["scylla", "cassandra", "orm", "sqlx", "truffle"]
categories = ["database"]
authors = [
"Carter Himmel <carter@truffle.vip>"
Expand Down
1 change: 1 addition & 0 deletions book/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/book
15 changes: 15 additions & 0 deletions book/book.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[book]
src = "src"
title = "scyllax Documentation"
authors = ["Carter Himmel <carter@truffle.vip>"]
language = "en"

[output.html]
git-repository-url = "https://github.com/trufflehq/scyllax/tree/main/book"
edit-url-template = "https://github.com/trufflehq/scyllax/edit/main/book/{path}"

[output.html.playground]
runnable = false

[output.html.redirect]
"/example.html" = "../example/README.md"
3 changes: 3 additions & 0 deletions book/src/404.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Document not found (404)

This URL is invalid, sorry. Try the search instead!
37 changes: 37 additions & 0 deletions book/src/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Getting Started

Scyllax is a query system (and ORM kinda) for Scylla. It is a work in progress and is not ready for production use.

# Installation
Although scyllax depends on scylla internally, it's recommended to have it installed if you decide to use some values from scylla.
Additionally, while in alpha, there is no `tracing` flag, so you must also install tracing.

```toml
scylla = "0.9"
scyllax = "0.1.8-alpha"
tracing = "0.1"
```

Scyllax's prelude includes everything you'll need, so import it at the top of your file:

```rust
use scyllax::prelude::*;
```

# Creating an executor
Your queries will need to be ran by an Executor. Creating one is simple. You can use the [`create_session`](https://docs.rs/scyllax/0.1.8-alpha/scyllax/executor/fn.create_session.html) function provided by scyllax, and pass it to a new Executor.

```rust
#use scyllax::prelude::*;
#
#[tokio::main]
fn main() {
let known_nodes = std::env::var("SCYLLA_NODES")
.expect("SCYLLA_NODES must be set");
let known_nodes = known_nodes.split(',').collect::<Vec<_>>();
let default_keyspace = std::env::var("SCYLLA_DEFAULT_KEYSPACE").ok();

let session = create_session(known_nodes, default_keyspace).await?;
let executor = Executor::with_session(session);
}
```
11 changes: 11 additions & 0 deletions book/src/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Summary

- [Introduction](./README.md)

- [Creating entities](./creating_entities/README.md)
- [camelCase Columns](./creating_entities/camelcase_columns.md)
- [JSON columns](./creating_entities/json_columns.md)
- [Counter columns](./creating_entities/counter_columns.md)
- [Select Queries](./select_queries/README.md)
- [Delete Queries](./delete_queries/README.md)
- [Upsert Queries](./upsert_queries/README.md)
23 changes: 23 additions & 0 deletions book/src/creating_entities/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Creating entities

Creating a new entity is super simple. Simply use the [`scyllax::Entity`](https://docs.rs/scyllax/latest/scyllax/derive.Entity.html) macro on a struct, and it'll implement the necessary symbols and traits.

```rust
#use scyllax::prelude::*;
#
#[derive(Clone, Debug, PartialEq, Entity, FromRow, ValueList)]
pub struct PersonEntity {
#[pk]
pub id: uuid::Uuid,
pub email: String,
pub created_at: i64,
}
```
Since `id` is a partition key, it must be annotated with `#[pk]`.
**Clustering columns must be treated the same way**.

This is so that, when eventually using the `upsert_query` macro, scyllax will use the column in the where clause rather than the set clause.

You're also welcome to use the `#[entity]` macro instead of deriving `Clone`, `Debug`, `PartialEq`, `Entity`, `FromRow`, and `ValueList` manually. That's what'll be used in the rst of this book.

A list of possible column types can be found at [scylla::frame::response::result::CqlValue](https://docs.rs/scylla/latest/scylla/frame/response/result/enum.CqlValue.html).
15 changes: 15 additions & 0 deletions book/src/creating_entities/camelcase_columns.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# camelCase Columns
If you have some column names you can't change to work with the Rust naming convention, you can use the `rename` attribute on an entity column to rename it in queries.

```rust
#use scyllax::prelude::*;
#
#[entity]
pub struct PersonEntity {
#[pk]
pub id: uuid::Uuid,
pub email: String,
#[rename = "createdAt"]
pub created_at: i64,
}
```
18 changes: 18 additions & 0 deletions book/src/creating_entities/counter_columns.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Counter columns
If you have a table that uses scylla's [`counter`](https://opensource.docs.scylladb.com/stable/cql/types.html#counters) type, you can use the `#[counter]` attribute macro on an entity column along with using the [`scylla::frame::value::Counter`](https://docs.rs/scylla/latest/scylla/frame/value/struct.Counter.html) type.

```rust
#use scyllax::prelude::*;
#
#[entity]
pub struct PersonLoginEntity {
#[pk]
pub id: uuid::Uuid,
#[pk]
pub person_id: uuid::Uuid,
#[counter]
pub count: scylla::frame::value::Counter,
}
```

Similarly to `#[pk]`, the `#[counter]` attribute also tells the upsert macro how to use the column in the query.
26 changes: 26 additions & 0 deletions book/src/creating_entities/json_columns.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# JSON columns
If you want something similar to postgres's [`json`](https://www.postgresql.org/docs/current/datatype-json.html) type, you can use the `#[json]` attribute macro on a struct.

```rust
#use scyllax::prelude::*;
#
#
/// Represents data from a person
#[json_data]
pub struct PersonData {
#[serde(rename = "stripeId")]
pub stripe_id: Option<String>,
}

#[entity]
pub struct PersonEntity {
#[pk]
pub id: uuid::Uuid,
pub email: String,
pub data: Option<PersonData>
#[rename = "createdAt"]
pub created_at: i64,
}
```

`json_data` uses serde `Deserialize` and `Serialize` under the hood, so you're welcome to use any of their macros.
36 changes: 36 additions & 0 deletions book/src/delete_queries/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Delete Queries
Writing delete queries, which is pretty much the same as [Select Queries](../select_queries/index.html), is incredibly easy with the `delete_query` macro.

Simply create a struct with the fields you want to select, and annotate it with the `#[select_query]` macro.

```rust
#use scyllax::prelude::*;
#
#\#[entity]
#pub struct PersonEntity {
# #[pk]
# pub id: uuid::Uuid,
# pub email: String,
# #[rename = "createdAt"]
# pub created_at: i64,
#}
#
#[delete_query(
query = "delete from person where id = ?",
entity_type = "PersonEntity"
)]
pub struct DeletePersonById {
pub id: Uuid,
}
```

Then, you can pass it to the executor you made in [Introduction](../index.html).
```rust,ignore
let query = DeletePersonById {
id: Uuid::from_str("00000000-0000-0000-0000-000000000000")?,
};
let res = executor
.execute_delete(query)
.await?
```
36 changes: 36 additions & 0 deletions book/src/select_queries/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Select Queries
Writing select queries is incredibly easy with the `select_query` macro.

Simply create a struct with the fields you want to select, and annotate it with the `#[select_query]` macro.

```rust
#use scyllax::prelude::*;
#
#\#[entity]
#pub struct PersonEntity {
# #[pk]
# pub id: uuid::Uuid,
# pub email: String,
# #[rename = "createdAt"]
# pub created_at: i64,
#}
#
#[select_query(
query = "select * from person where id = ? limit 1",
entity_type = "PersonEntity"
)]
pub struct GetPersonById {
pub id: Uuid,
}
```

Then, you can pass it to the executor you made in [Introduction](../index.html).
```rust,ignore
let query = GetPersonById {
id: Uuid::from_str("00000000-0000-0000-0000-000000000000")?,
};
let res = executor
.execute_select(query)
.await?
```
47 changes: 47 additions & 0 deletions book/src/upsert_queries/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Upsert Queries
Now listen up. Upsert queries with scyllax are special. You don't have to hand write anything. In conjunction with `#[pk]`, `#[counter]`, and `#[json]`, the `upsert_query` macro will generate the query for you. Simply apply the `#[upsert_query]` macro to tne entity struct.

```rust
#use scyllax::prelude::*;
#
#[entity]
#[upsert_query(table = "person", name = UpsertPerson)]
pub struct PersonEntity {
#[pk]
pub id: uuid::Uuid,
pub email: String,
#[rename = "createdAt"]
pub created_at: i64,
}
```

The structure will look a little like:
```rust,ignore
pub struct UpsertPerson {
///The id of the PersonEntity
pub id: uuid::Uuid,
///The email of the PersonEntity
pub email: scyllax::prelude::MaybeUnset<String>,
///The created_at of the PersonEntity
pub created_at: scyllax::prelude::MaybeUnset<i64>,
}
```
and the generated query will look a little like:
```cql
update person set email = :email, age = :age, data = :data, \"createdAt\" = :created_at where id = :id;
```

`MaybeUnset` is used to tell scylla if the field is not provided to the query, it should be ignored, and not overwritten. Every [Value](https://docs.rs/scylla/latest/scylla/frame/value/trait.Value.html) can be used with `MaybeUnset`.

Once you've built your query, you can pass it to an Executor.
```rust,ignore
let id = v1_uuid();
let query = UpsertPerson {
id,
email: "foo@scyllax.local".to_string().into(),
created_at: MaybeUnset::Unset,
};
let res = executor.execute_upsert(query).await?;
```
2 changes: 1 addition & 1 deletion example/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ async fn main() -> anyhow::Result<()> {
let upsert_id = v1_uuid();
let query = UpsertPerson {
id: upsert_id,
email: MaybeUnset::Set("foo21@scyllax.local".to_string()),
email: "foo21@scyllax.local".to_string().into(),
age: MaybeUnset::Set(Some(21)),
data: MaybeUnset::Set(Some(PersonData {
stripe_id: Some("stripe_id".to_string()),
Expand Down

0 comments on commit 7aec298

Please sign in to comment.