Skip to content

Commit

Permalink
Merge pull request #14 from wslongchen/0.2.0
Browse files Browse the repository at this point in the history
feat(0.2.0): Added SQLite support
  • Loading branch information
wslongchen authored Sep 5, 2021
2 parents 631dba2 + b165d4c commit 79d7d29
Show file tree
Hide file tree
Showing 16 changed files with 1,057 additions and 310 deletions.
24 changes: 12 additions & 12 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
[package]
name = "akita"
version = "0.2.10"
version = "0.2.11"
authors = ["mrpan <[email protected]>"]
edition = "2018"
description = "Akita.Mini Database Helper For MySQL."
description = "Akita - Mini orm for rust."
readme = "README.md"
keywords = ["akita", "mysql", "sql"]
keywords = ["akita", "orm", "mysql", "sqlite"]
categories = ["data-structures", "database-implementations"]
homepage = "https://github.com/wslongchen/akita"
repository = "https://github.com/wslongchen/akita"
documentation = "https://docs.rs/akita"
license = "MIT"

[dependencies]
akita_derive = {version = "0.2.5", path = "./akita_derive"}
mysql = {version = "19.0.1"}
mysql = {version = "20.1.0", optional = true}
rusqlite = {version = "0.21.0", optional = true}
bigdecimal = "0.3.0"
r2d2 = {version = "0.8.9"}
chrono = { version = "0.4", features = ["serde"]}
uuid = {version = "0.8.2", features = ["serde", "v4"]}
Expand All @@ -22,25 +25,22 @@ log = "0.4"
twox-hash = "1"
url = "2.2.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"


[dev-dependencies]
akita_derive = { version = "0.2.0", path = "./akita_derive" }

[package.metadata.playground]
# features = ["akita-mysql"]

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
# features = ["akita-mysql"]
features = ["akita-mysql"]

### FEATURES #################################################################

[features]
# default = []

# Provide mysql pool with r2d2.
# akita-mysql = []
akita-mysql = ["mysql"]

# Provide impls for HashMap<K, V>.
# Requires a dependency on the Rust standard library.
std = []
akita-sqlite = ["rusqlite"]
20 changes: 17 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Akita &emsp; [![Build Status]][actions] [![Latest Version]][crates.io] [![akita: rustc 1.13+]][Rust 1.13] [![akita_derive: rustc 1.31+]][Rust 1.31]

[Build Status]: https://img.shields.io/docsrs/akita/0.2.10?style=plastic
[Build Status]: https://img.shields.io/docsrs/akita/0.2.11?style=plastic
[actions]: https://github.com/wslongchen/akita/actions?query=branch%3Amaster
[Latest Version]: https://img.shields.io/crates/v/akita?style=plastic
[crates.io]: https://crates.io/crates/akita
Expand All @@ -9,13 +9,22 @@
[Rust 1.13]: https://blog.rust-lang.org/2016/11/10/Rust-1.13.html
[Rust 1.31]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html

**Akita is a mini orm framework for MySQL.**
**Akita - Mini orm for rust with SQLite & MySQL.**

This create offers:
* MySql database's helper in pure rust;
* SQLite database's helper in pure rust;
* A mini orm framework (With MySQL/SQLite)。

Features:

* Other Database support, i.e. support Oracle, MSSQL...;
* support of named parameters for custom condition;
---

You may be looking for:

- [An overview of Akita (Coming Soon...)]()
- [An overview of Akita](https://crates.io/crates/akita)
- [Examples](https://github.com/wslongchen/akita/blob/0.2.0/example/simple.rs)
- [API documentation](https://docs.rs/akita/0.1.6/akita/)
- [Release notes](https://github.com/wslongchen/akita/releases)
Expand Down Expand Up @@ -76,6 +85,11 @@ fn main() {
```


## Feature.

* ```akita-mysql``` - to use mysql
* ```akita-sqlite``` - to use sqlite

## Annotions.

* ```Table``` - to make Akita work with structs
Expand Down
Binary file added example/akita.sqlite3
Binary file not shown.
83 changes: 83 additions & 0 deletions src/comm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,87 @@ pub fn extract_datatype_with_capacity(data_type: &str) -> (String, Option<Capaci
} else {
(data_type.to_owned(), None)
}
}


fn trim_parenthesis(arg: &str) -> &str {
arg.trim_start_matches('(').trim_end_matches(')')
}

pub fn maybe_trim_parenthesis(arg: &str) -> &str {
if arg.starts_with('(') && arg.ends_with(')') {
trim_parenthesis(arg)
} else {
arg
}
}


#[macro_export]
macro_rules! cfg_if {
// match if/else chains with a final `else`
(
$(
if #[cfg( $i_meta:meta )] { $( $i_tokens:tt )* }
) else+
else { $( $e_tokens:tt )* }
) => {
$crate::cfg_if! {
@__items () ;
$(
(( $i_meta ) ( $( $i_tokens )* )) ,
)+
(() ( $( $e_tokens )* )) ,
}
};

// match if/else chains lacking a final `else`
(
if #[cfg( $i_meta:meta )] { $( $i_tokens:tt )* }
$(
else if #[cfg( $e_meta:meta )] { $( $e_tokens:tt )* }
)*
) => {
$crate::cfg_if! {
@__items () ;
(( $i_meta ) ( $( $i_tokens )* )) ,
$(
(( $e_meta ) ( $( $e_tokens )* )) ,
)*
}
};

// Internal and recursive macro to emit all the items
//
// Collects all the previous cfgs in a list at the beginning, so they can be
// negated. After the semicolon is all the remaining items.
(@__items ( $( $_:meta , )* ) ; ) => {};
(
@__items ( $( $no:meta , )* ) ;
(( $( $yes:meta )? ) ( $( $tokens:tt )* )) ,
$( $rest:tt , )*
) => {
// Emit all items within one block, applying an appropriate #[cfg]. The
// #[cfg] will require all `$yes` matchers specified and must also negate
// all previous matchers.
#[cfg(all(
$( $yes , )?
not(any( $( $no ),* ))
))]
$crate::cfg_if! { @__identity $( $tokens )* }

// Recurse to emit all other items in `$rest`, and when we do so add all
// our `$yes` matchers to the list of `$no` matchers as future emissions
// will have to negate everything we just matched as well.
$crate::cfg_if! {
@__items ( $( $no , )* $( $yes , )? ) ;
$( $rest , )*
}
};

// Internal macro to make __apply work out right for different match types,
// because of how macros match/expand stuff.
(@__identity $( $tokens:tt )* ) => {
$( $tokens )*
};
}
33 changes: 31 additions & 2 deletions src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@ use std::{convert::TryFrom, ops::Deref};

use url::Url;

use crate::{AkitaError, data::Rows, information::{DatabaseName, TableDef, TableName,}, mysql::MysqlDatabase, pool::LogLevel, value::Value};
cfg_if! {if #[cfg(feature = "akita-sqlite")]{
use crate::platform::sqlite::SqliteDatabase;
}}

cfg_if! {if #[cfg(feature = "akita-mysql")]{
use crate::platform::mysql::MysqlDatabase;
}}

use crate::{AkitaError, cfg_if, data::Rows, information::{DatabaseName, TableDef, TableName}, value::Value};


pub trait Database {
Expand All @@ -12,7 +20,7 @@ pub trait Database {

fn rollback_transaction(&mut self) -> Result<(), AkitaError>;

fn execute_result(&mut self, sql: &str, param: &[&Value], log: Option<LogLevel>) -> Result<Rows, AkitaError>;
fn execute_result(&mut self, sql: &str, param: &[&Value]) -> Result<Rows, AkitaError>;

fn get_table(&mut self, table_name: &TableName) -> Result<Option<TableDef>, AkitaError>;

Expand All @@ -33,29 +41,41 @@ pub trait Database {


pub enum DatabasePlatform {
#[cfg(feature = "akita-mysql")]
Mysql(Box<MysqlDatabase>),
#[cfg(feature = "akita-sqlite")]
Sqlite(Box<SqliteDatabase>),
}

impl Deref for DatabasePlatform {
type Target = dyn Database;

fn deref(&self) -> &Self::Target {
match *self {
#[cfg(feature = "akita-mysql")]
DatabasePlatform::Mysql(ref mysql) => mysql.deref(),
#[cfg(feature = "akita-sqlite")]
DatabasePlatform::Sqlite(ref sqlite) => sqlite.deref(),
}
}
}

impl std::ops::DerefMut for DatabasePlatform {
fn deref_mut(&mut self) -> &mut Self::Target {
match *self {
#[cfg(feature = "akita-mysql")]
DatabasePlatform::Mysql(ref mut mysql) => mysql.deref_mut(),
#[cfg(feature = "akita-sqlite")]
DatabasePlatform::Sqlite(ref mut sqlite) => sqlite.deref_mut(),
}
}
}

pub(crate) enum Platform {
#[cfg(feature = "akita-mysql")]
Mysql,
#[cfg(feature = "akita-sqlite")]
Sqlite(String),
Unsupported(String),
}

Expand All @@ -68,7 +88,16 @@ impl<'a> TryFrom<&'a str> for Platform {
Ok(url) => {
let scheme = url.scheme();
match scheme {
#[cfg(feature = "akita-mysql")]
"mysql" => Ok(Platform::Mysql),
#[cfg(feature = "akita-sqlite")]
"sqlite" => {
let host = url.host_str().unwrap_or_default();
let path = url.path();
let path = if path == "/" { "" } else { path };
let db_file = format!("{}{}", host, path);
Ok(Platform::Sqlite(db_file))
},
_ => Ok(Platform::Unsupported(scheme.to_string())),
}
}
Expand Down
15 changes: 14 additions & 1 deletion src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub enum AkitaError {
MissingTable(String),
MissingField(String),
MySQLError(String),
SQLiteError(String),
ExcuteSqlError(String, String),
DataError(String),
R2D2Error(String),
Expand All @@ -35,6 +36,7 @@ impl fmt::Display for AkitaError {
AkitaError::MissingField(ref err) => err.fmt(f),
AkitaError::RedundantField(ref err) => err.fmt(f),
AkitaError::MySQLError(ref err) => err.fmt(f),
AkitaError::SQLiteError(ref err) => err.fmt(f),
AkitaError::R2D2Error(ref err) => err.fmt(f),
}
}
Expand All @@ -56,6 +58,7 @@ impl std::error::Error for AkitaError {
AkitaError::MissingField(ref err) => err,
AkitaError::RedundantField(ref err) => err,
AkitaError::MySQLError(ref err) => err,
AkitaError::SQLiteError(ref err) => err,
AkitaError::R2D2Error(ref err) => err,
}
}
Expand All @@ -75,7 +78,7 @@ impl From<ParseError> for AkitaError {
}
}


#[cfg(feature = "akita-mysql")]
impl From<mysql::Error> for AkitaError {
fn from(err: mysql::Error) -> Self {
AkitaError::MySQLError(err.to_string())
Expand All @@ -88,18 +91,28 @@ impl From<r2d2::Error> for AkitaError {
}
}

#[cfg(feature = "akita-mysql")]
impl From<mysql::UrlError> for AkitaError {
fn from(err: mysql::UrlError) -> Self {
AkitaError::MySQLError(err.to_string())
}
}

#[cfg(feature = "akita-sqlite")]
impl From<rusqlite::Error> for AkitaError {
fn from(err: rusqlite::Error) -> Self {
AkitaError::SQLiteError(err.to_string())
}
}

#[cfg(feature = "akita-mysql")]
impl From<mysql::FromValueError> for AkitaError {
fn from(err: mysql::FromValueError) -> Self {
AkitaError::MySQLError(err.to_string())
}
}

#[cfg(feature = "akita-mysql")]
impl From<mysql::FromRowError> for AkitaError {
fn from(err: mysql::FromRowError) -> Self {
AkitaError::MySQLError(err.to_string())
Expand Down
Loading

0 comments on commit 79d7d29

Please sign in to comment.