Skip to content
Draft
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
61 changes: 39 additions & 22 deletions geekorm-sql/src/builder/columns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,23 @@ impl ColumnOptions {
auto_increment: true,
}
}

/// Not null options
pub fn not_null() -> Self {
ColumnOptions {
not_null: true,
..Default::default()
}
}

/// Unique options
pub fn unique() -> Self {
ColumnOptions {
unique: true,
not_null: true,
..Default::default()
}
}
}

impl ToSql for Column {
Expand All @@ -110,23 +127,25 @@ impl ToSql for Column {
QueryType::Create => {
stream.push_str(&self.name);
stream.push(' ');
self.column_type

let opts = self
.column_type
.to_sql_with_options(&self.column_options, query)?;
stream.push_str(&opts);
}
_ => {
let name = self.name();

stream.push_str(&name);

if let Some(alias) = &self.alias {
if !alias.is_empty() {
stream.push_str(" AS ");
stream.push_str(alias);
}
}

if query.joins.is_empty() {
stream.push_str(&name);
} else {
if !query.joins.is_empty() {
let table = query.find_table_default().unwrap();
let fullname = table.get_fullname(name.as_str());
stream.push_str(&fullname);
Expand All @@ -145,18 +164,6 @@ impl ToSql for Columns {
sql.push(col.to_sql(query)?);
}

for foreign_key in self.get_foreign_keys() {
let (ctable, ccolumn) = foreign_key.get_foreign_key().unwrap();

sql.push("FOREIGN KEY (".to_string());
sql.push(foreign_key.name.clone());
sql.push(") REFERENCES ".to_string());
sql.push(ctable.to_string());
sql.push("(".to_string());
sql.push(ccolumn.to_string());
sql.push(")".to_string());
}

stream.push_str(&sql.join(", "));
Ok(())
}
Expand Down Expand Up @@ -218,8 +225,12 @@ mod tests {
ColumnOptions::primary_key(),
)),
Column::from(("name".to_string(), ColumnType::Text)),
Column::from(("email".to_string(), ColumnType::Text)),
Column::from(("image_id".to_string(), ColumnType::ForeignKey)),
Column::from((
"email".to_string(),
ColumnType::Text,
ColumnOptions::unique(),
)),
Column::new_foreign_key("image_id", "Images.id"),
])
.into(),
}
Expand All @@ -238,6 +249,15 @@ mod tests {
assert_eq!(column_sql.as_str(), "id");
}

#[test]
fn test_column_foreign_key() {
let column = Column::new_foreign_key("image_id", "Images.id");
let (foreign_key_table, foreign_key_col) = column.get_foreign_key().unwrap();

assert_eq!(foreign_key_table, "Images");
assert_eq!(foreign_key_col, "id");
}

#[test]
fn test_columns_to_sql() {
let table = table();
Expand All @@ -246,9 +266,6 @@ mod tests {

let columns = Columns::to_sql(&table.columns, &query).unwrap();

assert_eq!(
columns.as_str(),
"id, name, email, image_id, FOREIGN KEY (image_id) REFERENCES images(id)"
);
assert_eq!(columns.as_str(), "id, name, email, image_id");
}
}
20 changes: 10 additions & 10 deletions geekorm-sql/src/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::{Error, Query, QueryBackend, ToSql, Value, Values};
use columns::Columns;

/// Query Type enum
#[derive(Debug, Clone, Default)]
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub enum QueryType {
/// Create Query
Create,
Expand Down Expand Up @@ -226,7 +226,7 @@ impl<'a> QueryBuilder<'a> {
.unwrap()
}
}
} else if let Some(table) = self.find_table("self") {
} else if let Some(table) = self.find_table_default() {
table
} else {
self.set_error(Error::QueryBuilderError {
Expand Down Expand Up @@ -263,43 +263,43 @@ impl<'a> QueryBuilder<'a> {

/// Where clause for equals
pub fn where_eq(&mut self, column: &str, value: impl Into<Value>) -> &mut Self {
QueryBuilder::add_where(self, column, QueryCondition::Eq, value.into());
self.add_where(column, QueryCondition::Eq, value.into());
self
}

/// Where clause for not equals
pub fn where_ne(&mut self, column: &str, value: impl Into<Value>) -> &mut Self {
QueryBuilder::add_where(self, column, QueryCondition::Ne, value.into());
self.add_where(column, QueryCondition::Ne, value.into());
self
}

/// Where clause for like
pub fn where_like(&mut self, column: &str, value: impl Into<Value>) -> &mut Self {
QueryBuilder::add_where(self, column, QueryCondition::Like, value.into());
self.add_where(column, QueryCondition::Like, value.into());
self
}

/// Where clause for greater than
pub fn where_gt(&mut self, column: &str, value: impl Into<Value>) -> &mut Self {
QueryBuilder::add_where(self, column, QueryCondition::Gt, value.into());
self.add_where(column, QueryCondition::Gt, value.into());
self
}

/// Where clause for less than
pub fn where_lt(&mut self, column: &str, value: impl Into<Value>) -> &mut Self {
QueryBuilder::add_where(self, column, QueryCondition::Lt, value.into());
self.add_where(column, QueryCondition::Lt, value.into());
self
}

/// Where clause for greater than or equal to
pub fn where_gte(&mut self, column: &str, value: impl Into<Value>) -> &mut Self {
QueryBuilder::add_where(self, column, QueryCondition::Gte, value.into());
self.add_where(column, QueryCondition::Gte, value.into());
self
}

/// Where clause for less than or equal to
pub fn where_lte(&mut self, column: &str, value: impl Into<Value>) -> &mut Self {
QueryBuilder::add_where(self, column, QueryCondition::Lte, value.into());
self.add_where(column, QueryCondition::Lte, value.into());
self
}

Expand Down Expand Up @@ -373,7 +373,7 @@ impl<'a> QueryBuilder<'a> {
}

fn validate_table_column(&self, column: &str) -> Result<bool, Error> {
if let Some(table) = self.find_table("self") {
if let Some(table) = self.find_table_default() {
Ok(table.columns.contains(&column))
} else {
return Err(Error::QueryBuilderError {
Expand Down
1 change: 1 addition & 0 deletions geekorm-sql/src/builder/queries/count.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ impl QueryType {
if let Some(ref alias) = table.alias {
table.alias(alias.clone());
}

table.to_sql_stream(&mut full_query, query).unwrap();

// WHERE
Expand Down
24 changes: 21 additions & 3 deletions geekorm-sql/src/builder/queries/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,26 @@ impl QueryType {
let mut full_query = String::new();
if let Some(table) = query.find_table_default() {
full_query.push_str("CREATE TABLE IF NOT EXISTS ");
full_query.push_str(&table.name);
full_query.push_str(table.name);

full_query.push_str(" (");

table.columns.to_sql_stream(&mut full_query, query).unwrap();
full_query.push(')');

// Only add foreign keys in CREATE queries
for foreign_key in table.get_foreign_keys() {
let (ctable, ccolumn) = foreign_key.get_foreign_key().unwrap();

full_query.push_str("FOREIGN KEY (");
full_query.push_str(&foreign_key.name);

full_query.push_str(") REFERENCES ");
full_query.push_str(ctable);
full_query.push('(');
full_query.push_str(ccolumn);
full_query.push(')');
}
}
full_query.push(';');

Expand Down Expand Up @@ -42,7 +56,11 @@ mod tests {
ColumnOptions::primary_key(),
)),
Column::from(("name".to_string(), ColumnType::Text)),
Column::from(("email".to_string(), ColumnType::Text)),
Column::from((
"email".to_string(),
ColumnType::Text,
ColumnOptions::unique(),
)),
])
.into(),
}
Expand All @@ -58,7 +76,7 @@ mod tests {

assert_eq!(
sql,
"CREATE TABLE IF NOT EXISTS Test (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, email TEXT UNIQUE);"
"CREATE TABLE IF NOT EXISTS Test (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, email TEXT NOT NULL UNIQUE);"
);
}
}
12 changes: 7 additions & 5 deletions geekorm-sql/src/builder/queries/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ impl QueryType {
table_expr.to_sql_stream(&mut full_query, query).unwrap();

// WHERE
query
.where_clause
.to_sql_stream(&mut full_query, query)
.unwrap();
if !query.where_clause.is_empty() {
query
.where_clause
.to_sql_stream(&mut full_query, query)
.unwrap();
}
}

full_query.push(';');
Expand Down Expand Up @@ -56,7 +58,7 @@ mod tests {
let table = table();
let query = QueryBuilder::delete()
.table(&table)
.where_primary_key(1)
.where_eq("id", 1)
.build()
.unwrap();

Expand Down
8 changes: 4 additions & 4 deletions geekorm-sql/src/builder/queries/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ mod tests {
)),
Column::from(("name".to_string(), ColumnType::Text)),
Column::from(("email".to_string(), ColumnType::Text)),
Column::from(("image_id".to_string(), ColumnType::ForeignKey)),
Column::new_foreign_key("image_id", "Images.id"),
])
.into(),
}
Expand All @@ -99,7 +99,7 @@ mod tests {
.build()
.unwrap();

assert_eq!(query.query, "SELECT id, name, email FROM Test;");
assert_eq!(query.query, "SELECT id, name, email, image_id FROM Test;");
}

#[test]
Expand All @@ -114,7 +114,7 @@ mod tests {

assert_eq!(
query.query,
"SELECT id, name, email FROM Test WHERE name = ?;"
"SELECT id, name, email, image_id FROM Test WHERE name = ?;"
);
assert_eq!(query.values.len(), 1);

Expand All @@ -136,7 +136,7 @@ mod tests {

assert_eq!(
query.query,
"SELECT id, name, email FROM Test ORDER BY name ASC, email DESC;"
"SELECT id, name, email, image_id FROM Test ORDER BY name ASC, email DESC;"
);
}
}
15 changes: 9 additions & 6 deletions geekorm-sql/src/builder/queries/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ impl QueryType {
let mut full_query = "UPDATE ".to_string();

if let Some(table) = query.find_table_default() {
let mut table = TableExpr::new(&table.name);
if let Some(ref alias) = table.alias {
table.alias(alias.clone());
let mut table_expr = TableExpr::new(table.name);

table.columns.to_sql_stream(&mut full_query, query).unwrap();

if let Some(ref alias) = table_expr.alias {
table_expr.alias(alias.clone());
}
table.to_sql_stream(&mut full_query, query).unwrap();
table_expr.to_sql_stream(&mut full_query, query).unwrap();

// WHERE
if !query.where_clause.is_empty() {
Expand Down Expand Up @@ -61,10 +64,10 @@ mod tests {
#[test]
fn test_update_query() {
let table = table();
let query = QueryBuilder::select()
let query = QueryBuilder::update()
.backend(QueryBackend::Sqlite)
.table(&table)
.where_primary_key("1")
.where_eq("id", 1)
.build()
.unwrap();

Expand Down
9 changes: 9 additions & 0 deletions geekorm-sql/src/builder/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ impl Table {
.find(|col| col.foreign_key.as_deref() == Some(&name))
}

/// Get all foreign key columns in the table.
pub fn get_foreign_keys(&self) -> Vec<&Column> {
self.columns
.columns
.iter()
.filter(|col| col.foreign_key.is_some())
.collect()
}

/// Get a column by its name or alias
pub fn find_column(&self, name: &str) -> Option<&Column> {
self.columns
Expand Down
Loading