Skip to content

Commit

Permalink
feat: functional
Browse files Browse the repository at this point in the history
  • Loading branch information
Fyko committed Sep 4, 2023
1 parent 11acdcf commit c98c251
Show file tree
Hide file tree
Showing 8 changed files with 1,156 additions and 52 deletions.
1,081 changes: 1,081 additions & 0 deletions example/expanded.rs

Large diffs are not rendered by default.

28 changes: 17 additions & 11 deletions example/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use entities::person::queries::{GetPersonByEmail, GetPersonById};
use scyllax::executor::create_session;
use entities::person::{
model::UpsertPerson,
queries::{GetPersonByEmail, GetPersonById},
};
use scyllax::prelude::*;
use scyllax::{executor::create_session, util::v1_uuid};
use tracing_subscriber::prelude::*;

pub mod entities;
Expand All @@ -13,34 +16,37 @@ async fn main() -> anyhow::Result<()> {
.init();

let known_nodes = std::env::var("SCYLLA_NODES").unwrap_or_else(|_| String::new());
let known_nodes = known_nodes.split(",").collect::<Vec<_>>();
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 exectuor = Executor::with_session(session);

// TODO: run init
let executor = Executor::with_session(session);

let by_email = GetPersonByEmail {
email: "[email protected]".to_string(),
};
let res_one = exectuor
let res_one = executor
.execute_select(by_email)
.await?
.expect("person not found");
tracing::debug!("query 1: {:?}", res_one);

let by_id = GetPersonById { id: res_one.id };
let res_two = exectuor
let res_two = executor
.execute_select(by_id)
.await?
.expect("person not found");
tracing::debug!("query 2: {:?}", res_two);

assert_eq!(res_one, res_two);

let test = exectuor.session.execute(r##"insert into person(id, email, "createdAt") values (b4ee3e46-46ce-11ee-be56-0242ac120002, '[email protected]', toUnixTimestamp(now()));"##, ())
.await?.rows();
tracing::debug!("test: {:?}", test);
let create = UpsertPerson {
id: v1_uuid(),
email: MaybeUnset::Set("[email protected]".to_string()),
age: MaybeUnset::Set(Some(21)),
created_at: MaybeUnset::Unset,
};
let res_three = executor.execute_upsert(create).await?;
tracing::debug!("query 3: {:?}", res_three);

Ok(())
}
27 changes: 14 additions & 13 deletions init.cql
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use scyllax;
create table person (
id timeuuid primary key,
email text,
age int,
-- camel case for the sake of backwards compat
"createdAt" timestamp
);
Expand All @@ -18,23 +19,23 @@ create materialized view person_by_email as
where email is not null and id is not null
primary key (email, id);

insert into person(id, email, "createdAt") values (e01e84d6-414c-11ee-be56-0242ac120002, '[email protected]', toUnixTimestamp(now()));
insert into person(id, email, "createdAt") values (e01e880a-414c-11ee-be56-0242ac120002, '[email protected]', toUnixTimestamp(now()));
insert into person(id, email, "createdAt") values (e01e89c2-414c-11ee-be56-0242ac120002, '[email protected]', toUnixTimestamp(now()));
insert into person(id, email, "createdAt") values (e01e8b2a-414c-11ee-be56-0242ac120002, '[email protected]', toUnixTimestamp(now()));
insert into person(id, email, "createdAt") values (e01e8db4-414c-11ee-be56-0242ac120002, '[email protected]', toUnixTimestamp(now()));
insert into person(id, email, "createdAt") values (e01e911a-414c-11ee-be56-0242ac120002, '[email protected]', toUnixTimestamp(now()));
insert into person(id, email, "createdAt") values (e01e9354-414c-11ee-be56-0242ac120002, '[email protected]', toUnixTimestamp(now()));
insert into person(id, email, age, "createdAt") values (e01e84d6-414c-11ee-be56-0242ac120002, '[email protected]', 25, toUnixTimestamp(now()));
insert into person(id, email, age, "createdAt") values (e01e880a-414c-11ee-be56-0242ac120002, '[email protected]', 25, toUnixTimestamp(now()));
insert into person(id, email, age, "createdAt") values (e01e89c2-414c-11ee-be56-0242ac120002, '[email protected]', 25, toUnixTimestamp(now()));
insert into person(id, email, age, "createdAt") values (e01e8b2a-414c-11ee-be56-0242ac120002, '[email protected]', 25, toUnixTimestamp(now()));
insert into person(id, email, age, "createdAt") values (e01e8db4-414c-11ee-be56-0242ac120002, '[email protected]', 25, toUnixTimestamp(now()));
insert into person(id, email, age, "createdAt") values (e01e911a-414c-11ee-be56-0242ac120002, '[email protected]', 25, toUnixTimestamp(now()));
insert into person(id, email, age, "createdAt") values (e01e9354-414c-11ee-be56-0242ac120002, '[email protected]', 25, toUnixTimestamp(now()));
insert into person(id, email, "createdAt") values (e01e94e4-414c-11ee-be56-0242ac120002, '[email protected]', toUnixTimestamp(now()));
insert into person(id, email, "createdAt") values (e01e9854-414c-11ee-be56-0242ac120002, '[email protected]', toUnixTimestamp(now()));
insert into person(id, email, age, "createdAt") values (e01e9854-414c-11ee-be56-0242ac120002, '[email protected]', 25, toUnixTimestamp(now()));
insert into person(id, email, "createdAt") values (e01e99ee-414c-11ee-be56-0242ac120002, '[email protected]', toUnixTimestamp(now()));
insert into person(id, email, "createdAt") values (e01e9b60-414c-11ee-be56-0242ac120002, '[email protected]', toUnixTimestamp(now()));
insert into person(id, email, age, "createdAt") values (e01e9b60-414c-11ee-be56-0242ac120002, '[email protected]', 48, toUnixTimestamp(now()));
insert into person(id, email, "createdAt") values (e01e9cc8-414c-11ee-be56-0242ac120002, '[email protected]', toUnixTimestamp(now()));
insert into person(id, email, "createdAt") values (e01e9e3a-414c-11ee-be56-0242ac120002, '[email protected]', toUnixTimestamp(now()));
insert into person(id, email, age, "createdAt") values (e01e9e3a-414c-11ee-be56-0242ac120002, '[email protected]', 22, toUnixTimestamp(now()));
insert into person(id, email, "createdAt") values (e01ea1d2-414c-11ee-be56-0242ac120002, '[email protected]', toUnixTimestamp(now()));
insert into person(id, email, "createdAt") values (e01ea380-414c-11ee-be56-0242ac120002, '[email protected]', toUnixTimestamp(now()));
insert into person(id, email, "createdAt") values (e01ea4f2-414c-11ee-be56-0242ac120002, '[email protected]', toUnixTimestamp(now()));
insert into person(id, email, "createdAt") values (e01ea682-414c-11ee-be56-0242ac120002, '[email protected]', toUnixTimestamp(now()));
insert into person(id, email, age, "createdAt") values (e01ea4f2-414c-11ee-be56-0242ac120002, '[email protected]', 26, toUnixTimestamp(now()));
insert into person(id, email, age, "createdAt") values (e01ea682-414c-11ee-be56-0242ac120002, '[email protected]', 18, toUnixTimestamp(now()));
insert into person(id, email, "createdAt") values (e01ea81c-414c-11ee-be56-0242ac120002, '[email protected]', toUnixTimestamp(now()));
insert into person(id, email, "createdAt") values (e01eab14-414c-11ee-be56-0242ac120002, '[email protected]', toUnixTimestamp(now()));
insert into person(id, email, age, "createdAt") values (e01eab14-414c-11ee-be56-0242ac120002, '[email protected]', 28, toUnixTimestamp(now()));
insert into person(id, email, "createdAt") values (e01eaca4-414c-11ee-be56-0242ac120002, '[email protected]', toUnixTimestamp(now()));
8 changes: 3 additions & 5 deletions scyllax-macros/src/entity.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use darling::{export::NestedMeta, FromMeta};
use crate::token_stream_with_error;
use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
use syn::{Data, DeriveInput, Expr, Field, ItemStruct};

use crate::{queries::upsert::upsert_impl, token_stream_with_error};
use syn::{Expr, Field, ItemStruct};

/// Attribute expand
/// Just adds the dervie macro to the struct.
Expand Down Expand Up @@ -34,7 +32,7 @@ pub fn expand(input: TokenStream) -> TokenStream {
}

/// EntityExt implementation
fn entity_impl(input: &ItemStruct, pks: &Vec<&Field>) -> TokenStream {
fn entity_impl(input: &ItemStruct, pks: &[&Field]) -> TokenStream {
let name = &input.ident;

let keys = input.fields.iter().map(get_field_name).collect::<Vec<_>>();
Expand Down
10 changes: 7 additions & 3 deletions scyllax-macros/src/queries/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ pub fn expand(args: TokenStream, item: TokenStream) -> TokenStream {
};

quote! {
#[derive(scylla::ValueList, std::fmt::Debug, std::clone::Clone, PartialEq, Hash)]
#input

#[scyllax::async_trait]
impl scyllax::SelectQuery<#entity_type, #return_type> for #struct_ident {
fn query() -> String {
Expand All @@ -91,6 +94,10 @@ pub fn expand(args: TokenStream, item: TokenStream) -> TokenStream {

async fn execute(self, db: &scyllax::Executor) -> anyhow::Result<scylla::QueryResult, scylla::transport::errors::QueryError> {
let query = Self::query();
tracing::debug!{
query,
"executing select"
};

db.session.execute(query, self).await
}
Expand All @@ -99,8 +106,5 @@ pub fn expand(args: TokenStream, item: TokenStream) -> TokenStream {
#parser
}
}

#[derive(scylla::ValueList, std::fmt::Debug, std::clone::Clone, PartialEq, Hash)]
#input
}
}
39 changes: 22 additions & 17 deletions scyllax-macros/src/queries/upsert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
use syn::{Field, ItemStruct};

use crate::{token_stream_with_error, entity::get_field_name};
use crate::{entity::get_field_name, token_stream_with_error};

#[derive(FromMeta)]
pub(crate) struct UpsertQueryOptions {
Expand Down Expand Up @@ -54,7 +54,7 @@ pub fn expand(args: TokenStream, input: TokenStream) -> TokenStream {
pub(crate) fn upsert_impl(
input: &ItemStruct,
opt: &UpsertQueryOptions,
pks: &Vec<&Field>,
pks: &[&Field],
) -> TokenStream {
let upsert_struct = &opt.name;
let upsert_table = &opt.table;
Expand All @@ -72,7 +72,7 @@ pub(crate) fn upsert_impl(
let ty = &f.ty;

quote! {
#ident: #ty
pub #ident: #ty
}
})
.collect::<Vec<_>>();
Expand All @@ -85,14 +85,14 @@ pub(crate) fn upsert_impl(
let ty = &f.ty;

quote! {
#ident: scyllax::prelude::MaybeUnset<#ty>
pub #ident: scyllax::prelude::MaybeUnset<#ty>
}
})
.collect::<Vec<_>>();

let expanded_upsert_struct = quote! {
#[derive(Debug, Clone)]
struct #upsert_struct {
pub struct #upsert_struct {
#(#expanded_pks,)*
#(#maybe_unset_fields,)*
}
Expand All @@ -105,13 +105,13 @@ pub(crate) fn upsert_impl(
.filter(|f| !pks.contains(f))
.map(|f| {
let ident = &f.ident.clone().unwrap();
let col = get_field_name(&f);
let errors = error_switchback(&f);
let col = get_field_name(f);
let errors = error_switchback(f);

quote! {
if let scyllax::prelude::MaybeUnset::Set(#ident) = &self.#ident {
// FIX: ident
fragments.push_str(concat!(stringify!(#col = ?), " "));
fragments.push_str(concat!(stringify!(#col = ?,), " "));

match variables.add_value(#ident) {
Ok(_) => (),
Expand All @@ -128,12 +128,11 @@ pub(crate) fn upsert_impl(
.filter(|f| pks.contains(f))
.map(|f| {
let ident = &f.ident.clone().unwrap();
let col = get_field_name(&f);
let errors = error_switchback(&f);
let col = get_field_name(f);
let errors = error_switchback(f);

quote! {
// FIX: ident
fragments.push_str(concat!(stringify!(where #col = ?, ), " "));
fragments.push_str(concat!(stringify!(where #col = ?,), " "));
match variables.add_value(&self.#ident) {
Ok(_) => (),
#errors
Expand All @@ -142,23 +141,24 @@ pub(crate) fn upsert_impl(
})
.collect::<Vec<_>>();

// return expanded_upsert_struct;

quote! {
#input

#expanded_upsert_struct

#[scyllax::async_trait]
impl scyllax::UpsertQuery<#struct_ident> for #upsert_struct {
fn query(
&self,
) -> Result<(String, scyllax::prelude::SerializedValues), scyllax::BuildUpsertQueryError> {
let mut fragments = String::from(stringify!(update #upsert_table set ));
let mut fragments = String::from(concat!(stringify!(update #upsert_table set ), " "));
let mut variables = scylla::frame::value::SerializedValues::new();

#(#expanded_variables)*

fragments.pop();
fragments.pop();
fragments.push_str(" ");

#(#expanded_pks)*

fragments.pop();
Expand All @@ -170,9 +170,14 @@ pub(crate) fn upsert_impl(
}


async fn execute(self, db: &scyllax::Executor) -> anyhow::Result<scyllax::QueryResult, scyllax::QueryError> {
async fn execute(self, db: &scyllax::Executor) -> Result<scyllax::QueryResult, scyllax::ScyllaxError> {
let (query, values) = Self::query(&self)?;

tracing::debug! {
query = ?query,
values = values.len(),
"executing upsert"
};
db.session.execute(query, values).await.map_err(|e| e.into())
}
}
Expand Down
14 changes: 12 additions & 2 deletions scyllax/src/executor.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{error::ScyllaxError, EntityExt, FromRow, SelectQuery, ValueList};
use crate::{error::ScyllaxError, EntityExt, FromRow, SelectQuery, UpsertQuery, ValueList};
use scylla::{
prepared_statement::PreparedStatement, query::Query, transport::errors::QueryError,
CachingSession, SessionBuilder,
CachingSession, QueryResult, SessionBuilder,
};

/// Creates a new [`CachingSession`] and returns it
Expand Down Expand Up @@ -54,4 +54,14 @@ impl Executor {
let res = query.execute(self).await?;
E::parse_response(res).await
}

/// Executes a [`UpsertQuery`] and returns the result
pub async fn execute_upsert<T: EntityExt<T> + FromRow + ValueList, E: UpsertQuery<T>>(
&self,
query: E,
) -> Result<QueryResult, ScyllaxError> {
let res = query.execute(self).await?;

Ok(res)
}
}
1 change: 0 additions & 1 deletion scyllax/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use anyhow::Result;
pub use error::BuildUpsertQueryError;
pub use scylla::{
prepared_statement::PreparedStatement, transport::errors::QueryError, QueryResult,
Expand Down

0 comments on commit c98c251

Please sign in to comment.