Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 31 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,41 @@ version = "0.1.0"
authors = ["Anit Nilay <anit.nilay20@gmail.com>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[workspace]
members = [
"beatrix_macro",
"beatrix_core",
"beatrix_helpers",
]

[features]
default = ["postgres"]
postgres = ["beatrix_core/postgres", "beatrix_macro/postgres"]
chrono = ["beatrix_core/chrono"]
mongo = ["beatrix_core/mongo", "beatrix_macro/mongo"]

[dependencies]
beatrix_macro = { path="beatrix_macro", version = "0.1.0" }
beatrix_core = { path="beatrix_core", version = "0.1.0" }
beatrix_helpers = { path="beatrix_helpers", version = "0.1.0" }

[dev-dependencies]
serde = "1"
tokio = "0.2.18"
dotenv = "*"
futures = "*"
# TODO: UPgrade to latest tokio
tokio = { version = "1.49.0", features = ["full"] }
dotenv = "0.15.0"
futures = "0.3.32"

[workspace]
members = [
"beatrix_macro",
"beatrix_core",
]
[[test]]
name = "mongo"
path = "tests/mongo.rs"
required-features = ["mongo"]

[[test]]
name = "table-macro"
path = "tests/rdms/postgres/table_macro.rs"
required-features = ["postgres"]

[[test]]
name = "date-time"
path = "tests/rdms/postgres/date_time.rs"
required-features = ["postgres", "chrono"]
21 changes: 16 additions & 5 deletions beatrix_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,24 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
mongodb = "1.1.1"
mongodb = { version = "3.5.1", optional = true }
serde = "1.0.119"
async-trait = "0.1.42"
thiserror = "1.0"
thiserror = "2.0.18"
futures = "0.3"
syn = { version = "2.0.115" }
tokio = { version = "1.49.0", features = ["full"] }
sqlx = { version = "0.8", features = [
"runtime-tokio",
"postgres",
"chrono"
], optional = true }
chrono = { version = "0.4.43", optional = true }

[features]
default = ["tokio-runtime"]
tokio-runtime = ["mongodb/tokio-runtime"]
async-std-runtime = ["mongodb/async-std-runtime"]
default = ["postgres"]
postgres = ["dep:sqlx", "sqlx/postgres"]
chrono = ["dep:chrono", "sqlx/chrono"]

#mongo
mongo = ["dep:mongodb"]
14 changes: 11 additions & 3 deletions beatrix_core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
pub mod mongo;
pub use mongodb;
pub use mongodb::bson;
#[cfg(feature = "postgres")]
pub mod relational;

pub use async_trait;

pub use sqlx;

// #[cfg(feature = "mongo")]
// pub mod mongo;
// #[cfg(feature = "mongo")]
// pub use mongodb;
// #[cfg(feature = "mongo")]
// pub use mongodb::bson;
6 changes: 3 additions & 3 deletions beatrix_core/src/mongo/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ use super::{
};

pub struct ModelCursor<T> {
cursor: Cursor,
cursor: Cursor<T>,
model: PhantomData<T>,
}

impl<T: MongoModel> ModelCursor<T> {
pub(crate) fn new(cursor: Cursor) -> Self {
pub(crate) fn new(cursor: Cursor<T>) -> Self {
Self {
model: std::marker::PhantomData,
cursor,
Expand All @@ -38,7 +38,7 @@ impl<T: MongoModel> Stream for ModelCursor<T> {
Poll::Ready(Some(Ok(doc))) => doc,
};

match MongoModel::from_bson(doc) {
match MongoModel::from_bson(doc.to_document()?) {
Ok(model) => Poll::Ready(Some(Ok(model))),
Err(err) => Poll::Ready(Some(Err(err)))
}
Expand Down
7 changes: 3 additions & 4 deletions beatrix_core/src/mongo.rs → beatrix_core/src/mongo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ where
self.set_id(ObjectId::new());
}

let doc = self.into_document()?;
let doc = self.to_document()?;
collection
.update_one(
doc! { "_id": self.id().unwrap() },
Expand All @@ -145,16 +145,15 @@ where
/// Returns error if ID is null.
async fn delete(&self, db: Database) -> Result<DeleteResult> {
let id = self
.id()
.ok_or_else(|| error::Error::ModelIdRequiredForOperation)?;
.id().ok_or(error::Error::ModelIdRequiredForOperation)?;

Ok(Self::collection(db)
.delete_one(doc! {"_id": id}, None)
.await?)
}

/// Convert instance to document.
fn into_document(&self) -> Result<Document> {
fn to_document(&self) -> Result<Document> {
match to_bson(self)? {
Bson::Document(doc) => Ok(doc),
bsn => Err(error::Error::ModelSerToDocument(bsn.element_type())),
Expand Down
141 changes: 141 additions & 0 deletions beatrix_core/src/relational/column.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
use std::marker::PhantomData;

use super::{
db::Database,
filters::{Expression, Filters},
};
use crate::relational::sql::SqlColumn;
use crate::{impl_column_for_characters, impl_comparison_for_column};

pub trait ColumnType: Sync + Send {
fn table_name(&self) -> &'static str;
fn column_name(&self) -> &'static str;
fn alias(&self) -> String;
}

impl<T: ?Sized + ColumnType, DB: Database> SqlColumn<DB> for T {
fn to_sql(&self, db: &DB) -> String {
format!(
"{}{}{} as {}{}{}",
db.backtick_open(),
self.column_name(),
db.backtick_close(),
db.backtick_open(),
self.alias(),
db.backtick_close()
)
}
}
impl<DB: Database> SqlColumn<DB> for Box<dyn ColumnType> {
fn to_sql(&self, db: &DB) -> String {
format!(
"{}{}{} as {}{}{}\n",
db.backtick_open(),
self.column_name(),
db.backtick_close(),
db.backtick_open(),
self.alias(),
db.backtick_close()
)
}
}

impl<DB: Database> SqlColumn<DB> for Vec<Box<dyn ColumnType>> {
fn to_sql(&self, db: &DB) -> String {
self.iter()
.map(|f| f.to_sql(db))
.collect::<Vec<String>>()
.join(", ")
}
}
impl<T: ColumnType + 'static, DB: Database> SqlColumn<DB> for Vec<Box<T>> {
fn to_sql(&self, db: &DB) -> String {
self.iter()
.map(|f| f.to_sql(db))
.collect::<Vec<String>>()
.join(", ")
}
}

#[derive(Clone)]
pub struct Column<T> {
pub table_name: &'static str,
pub column_name: &'static str,
pub alias: Option<String>,
pub _marker: PhantomData<T>,
}

impl<T> Column<T> {
pub fn new(table_name: &'static str, column_name: &'static str, alias: Option<String>) -> Self {
Self {
table_name,
column_name,
alias,
_marker: PhantomData,
}
}

pub fn column_name(&self) -> &str {
self.column_name
}

pub fn alias(&self) -> &str {
if let Some(alias) = &self.alias {
alias
} else {
self.column_name()
}
}

pub fn r#as(mut self, alias: &str) -> Self {
self.alias = Some(alias.to_string());
self
}
}

impl<T> ColumnType for Column<T>
where
T: Sync + Send,
{
fn table_name(&self) -> &'static str {
self.table_name
}

fn column_name(&self) -> &'static str {
self.column_name
}

fn alias(&self) -> String {
if let Some(alias) = &self.alias {
alias.clone()
} else {
self.column_name().to_string()
}
}
}

impl<T> Column<T>
where
T: Send + Sync + 'static + Clone,
{
pub fn eq(self, other: T) -> Filters<T, T> {
Filters {
column: self,
not: false,
value: other,
expression: Expression::Eq,
}
}

pub fn neq(self, other: T) -> Filters<T, T> {
Filters {
column: self,
not: true,
value: other,
expression: Expression::Neq,
}
}
}

impl_comparison_for_column!(i8, i16, i32, i64, f32, f64);
impl_column_for_characters!(char, String);
29 changes: 29 additions & 0 deletions beatrix_core/src/relational/data_type/bind.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use sqlx::{Database, Encode, Type};
// use super::Value;

// 1. The Trait definition
pub trait BindValue<DB: Database>: Send + Sync {
fn bind_to<'args>(&'args self, builder: &mut sqlx::QueryBuilder<'args, DB>);
fn box_clone(&self) -> Box<dyn BindValue<DB>>;
}

impl<DB: Database> Clone for Box<dyn BindValue<DB>> {
fn clone(&self) -> Self {
self.box_clone()
}
}

impl<T, DB> BindValue<DB> for T
where
DB: Database,
T: for<'q> Encode<'q, DB> + Type<DB>,
T: Send + Sync + Clone + 'static,
{
fn bind_to<'args>(&'args self, builder: &mut sqlx::QueryBuilder<'args, DB>) {
builder.push_bind(self.clone());
}

fn box_clone(&self) -> Box<dyn BindValue<DB>> {
Box::new(self.clone())
}
}
4 changes: 4 additions & 0 deletions beatrix_core/src/relational/data_type/chrono.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
use chrono::{DateTime, Local, NaiveDate, NaiveTime, Utc, NaiveDateTime};
use crate::impl_comparison_for_column;

impl_comparison_for_column!(NaiveDate, NaiveTime, NaiveDateTime, DateTime<Utc>, DateTime<Local>);
25 changes: 25 additions & 0 deletions beatrix_core/src/relational/data_type/macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#[macro_export]
macro_rules! impl_into_value {
($($t:ty => $variant:ident),*) => {
$(
impl $crate::relational::data_type::IntoValue for $t {
fn into_value(self) -> $crate::relational::data_type::Value {
$crate::relational::data_type::Value::$variant(self)
}
}
)*
};
}

#[macro_export]
macro_rules! impl_sql_for_character {
($($t:ty),*) => {
$(
impl $crate::relational::sql::Sql for $t {
fn to_sql(&self) -> String {
format!("'{}'", self)
}
}
)*
};
}
8 changes: 8 additions & 0 deletions beatrix_core/src/relational/data_type/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#[cfg(feature = "chrono")]
mod chrono;

mod macros;
pub(crate) mod bind;

use crate::impl_sql_for_character;
impl_sql_for_character!(char);
Loading
Loading