Ugly progress commit
This commit is contained in:
parent
b16cb8b8e4
commit
1776233a93
@ -30,6 +30,7 @@ struct QueryResult;
|
|||||||
pub struct DefaultDriver;
|
pub struct DefaultDriver;
|
||||||
|
|
||||||
impl DefaultDriver {
|
impl DefaultDriver {
|
||||||
|
/// Create a `DefaultDriver`
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
DefaultDriver {}
|
DefaultDriver {}
|
||||||
}
|
}
|
||||||
@ -61,7 +62,7 @@ pub trait DatabaseDriver: fmt::Debug {
|
|||||||
/// Quote the identifiers passed, so the database does not
|
/// Quote the identifiers passed, so the database does not
|
||||||
/// normalize the identifiers (eg, table, column, etc.)
|
/// normalize the identifiers (eg, table, column, etc.)
|
||||||
fn quote_identifier(&self, identifier: &str) -> String {
|
fn quote_identifier(&self, identifier: &str) -> String {
|
||||||
let mut identifier = &mut String::from(identifier);
|
let identifier = &mut String::from(identifier);
|
||||||
|
|
||||||
// If the identifier is actually a comma-separated list,
|
// If the identifier is actually a comma-separated list,
|
||||||
// recurse to quote each identifier in the list
|
// recurse to quote each identifier in the list
|
||||||
@ -78,13 +79,12 @@ pub trait DatabaseDriver: fmt::Debug {
|
|||||||
|
|
||||||
let trimmed_tiers = split_map_join(identifier, ".", |tier| {
|
let trimmed_tiers = split_map_join(identifier, ".", |tier| {
|
||||||
let tier = tier.trim();
|
let tier = tier.trim();
|
||||||
|
|
||||||
// Here where the quoting actually happens. Everything
|
|
||||||
// else is breaking down the identifier list for this.
|
|
||||||
if tier.starts_with(open_char) && tier.ends_with(close_char) {
|
if tier.starts_with(open_char) && tier.ends_with(close_char) {
|
||||||
return tier.to_string();
|
return tier.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Here where the quoting actually happens. Everything
|
||||||
|
// else is breaking down the identifier list for this.
|
||||||
format!("{}{}{}", &open_char, tier, &close_char)
|
format!("{}{}{}", &open_char, tier, &close_char)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ use super::*;
|
|||||||
pub struct MSSQL;
|
pub struct MSSQL;
|
||||||
|
|
||||||
impl MSSQL {
|
impl MSSQL {
|
||||||
|
/// Create a MSSQL Driver
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
MSSQL {}
|
MSSQL {}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ use super::*;
|
|||||||
pub struct MySQL;
|
pub struct MySQL;
|
||||||
|
|
||||||
impl MySQL {
|
impl MySQL {
|
||||||
|
/// Create a MySQL driver
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
MySQL {}
|
MySQL {}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ use super::*;
|
|||||||
pub struct Postgres;
|
pub struct Postgres;
|
||||||
|
|
||||||
impl Postgres {
|
impl Postgres {
|
||||||
|
/// Create a Postgres driver
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Postgres {}
|
Postgres {}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ use super::*;
|
|||||||
pub struct SQLite;
|
pub struct SQLite;
|
||||||
|
|
||||||
impl SQLite {
|
impl SQLite {
|
||||||
|
/// Create an SQLite driver
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
SQLite {}
|
SQLite {}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
//! # StringQB
|
//! # StringQB
|
||||||
//!
|
//!
|
||||||
//! A query builder using mostly strings, with methods following common SQL syntax
|
//! A query builder using mostly strings, with methods following common SQL syntax
|
||||||
// #![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
pub mod drivers;
|
pub mod drivers;
|
||||||
pub mod query_builder;
|
pub mod query_builder;
|
||||||
pub mod types;
|
|
||||||
|
|
||||||
/// Split a string, apply a closure to each substring,
|
/// Split a string, apply a closure to each substring,
|
||||||
/// then join the string back together
|
/// then join the string back together
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! This main file is just for temparary testing
|
//! This main file is just for temparary testing
|
||||||
use stringqb::drivers::postgres::Postgres;
|
use stringqb::drivers::postgres::Postgres;
|
||||||
use stringqb::query_builder::QueryBuilder;
|
use stringqb::query_builder::QueryBuilder;
|
||||||
use stringqb::types::{SQLType, Type};
|
// use stringqb::types::{SQLType, Type};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut qb = QueryBuilder::new(Postgres::new());
|
let mut qb = QueryBuilder::new(Postgres::new());
|
||||||
@ -17,6 +17,6 @@ fn main() {
|
|||||||
|
|
||||||
println!("QueryBuilder object: {:#?}", &qb);
|
println!("QueryBuilder object: {:#?}", &qb);
|
||||||
|
|
||||||
println!("SQLType mapping: {:#?}", SQLType::SmallInt(32));
|
// println!("SQLType mapping: {:#?}", SQLType::SmallInt(32));
|
||||||
println!("Type: {:#?}", Type(Box::new(1234567890)));
|
// println!("Type: {:#?}", Type(Box::new(1234567890)));
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ use std::any::Any;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::drivers::{DatabaseDriver, DefaultDriver};
|
use crate::drivers::{DatabaseDriver, DefaultDriver};
|
||||||
|
use crate::split_map_join;
|
||||||
|
|
||||||
/// The position of the wildcard(s)
|
/// The position of the wildcard(s)
|
||||||
/// for a `like` clause
|
/// for a `like` clause
|
||||||
@ -26,18 +27,16 @@ pub enum LikeWildcard {
|
|||||||
/// The type of SQL join
|
/// The type of SQL join
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum JoinType {
|
pub enum JoinType {
|
||||||
|
/// A `CROSS` join
|
||||||
|
Cross,
|
||||||
/// An `INNER` join
|
/// An `INNER` join
|
||||||
Inner,
|
Inner,
|
||||||
/// An `OUTER` join
|
/// An `OUTER` join
|
||||||
Outer,
|
Outer,
|
||||||
/// A `LEFT` join
|
/// A `LEFT (OUTER)` join
|
||||||
Left,
|
Left,
|
||||||
/// A `RIGHT` join
|
/// A `RIGHT (OUTER)` join
|
||||||
Right,
|
Right,
|
||||||
/// A `LEFT OUTER` join
|
|
||||||
LeftOuter,
|
|
||||||
/// A `RIGHT OUTER` join
|
|
||||||
RightOuter,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The sort direction
|
/// The sort direction
|
||||||
@ -47,7 +46,7 @@ pub enum OrderDirection {
|
|||||||
Asc,
|
Asc,
|
||||||
/// Sort Descending
|
/// Sort Descending
|
||||||
Desc,
|
Desc,
|
||||||
/// Random Sort
|
/// Random Sort (Not yet implemented!)
|
||||||
Rand,
|
Rand,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,6 +60,14 @@ enum QueryClauseType {
|
|||||||
WhereIn,
|
WhereIn,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum QueryType {
|
||||||
|
Select,
|
||||||
|
Insert,
|
||||||
|
Update,
|
||||||
|
Delete,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct QueryClause {
|
struct QueryClause {
|
||||||
clause_type: QueryClauseType,
|
clause_type: QueryClauseType,
|
||||||
@ -197,7 +204,18 @@ impl QueryBuilder {
|
|||||||
|
|
||||||
/// Set the fields to select from the database as a string
|
/// Set the fields to select from the database as a string
|
||||||
pub fn select(&mut self, fields: &str) -> &mut Self {
|
pub fn select(&mut self, fields: &str) -> &mut Self {
|
||||||
unimplemented!();
|
let fields = split_map_join(fields, ",", |s| s.trim().to_string());
|
||||||
|
|
||||||
|
// Split identifiers on `As` keyword so they can be quoted properly
|
||||||
|
// @TODO split identifiers on `as` keyword (needs to be case-insensitive)
|
||||||
|
|
||||||
|
// Quote the identifiers (where there was an `as` keyword)
|
||||||
|
|
||||||
|
// Rejoin those identifiers
|
||||||
|
|
||||||
|
self.state.append_select_string(&fields);
|
||||||
|
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the fields to select from the database as a Vector
|
/// Set the fields to select from the database as a Vector
|
||||||
@ -284,7 +302,7 @@ impl QueryBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
// Specify a condition for a `where` clause where a column has a value
|
/// Specify a condition for a `where` clause where a column has a value
|
||||||
pub fn where_eq(&mut self, key: &str, value: Box<dyn Any>) -> &mut Self {
|
pub fn where_eq(&mut self, key: &str, value: Box<dyn Any>) -> &mut Self {
|
||||||
self.r#where(key, "=", value)
|
self.r#where(key, "=", value)
|
||||||
}
|
}
|
||||||
@ -360,12 +378,11 @@ impl QueryBuilder {
|
|||||||
let condition = table + " ON " + &col + op + value;
|
let condition = table + " ON " + &col + op + value;
|
||||||
|
|
||||||
let join_type = match join_type {
|
let join_type = match join_type {
|
||||||
|
JoinType::Cross => "CROSS ",
|
||||||
JoinType::Left => "LEFT ",
|
JoinType::Left => "LEFT ",
|
||||||
JoinType::Inner => "INNER ",
|
JoinType::Inner => "INNER ",
|
||||||
JoinType::LeftOuter => "LEFT OUTER ",
|
|
||||||
JoinType::Outer => "OUTER ",
|
JoinType::Outer => "OUTER ",
|
||||||
JoinType::Right => "RIGHT ",
|
JoinType::Right => "RIGHT ",
|
||||||
JoinType::RightOuter => "RIGHT OUTER",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let conjunction = "\n".to_string() + join_type + "JOIN ";
|
let conjunction = "\n".to_string() + join_type + "JOIN ";
|
||||||
@ -438,26 +455,28 @@ impl QueryBuilder {
|
|||||||
|
|
||||||
/// Start a logical grouping in the current query
|
/// Start a logical grouping in the current query
|
||||||
pub fn group_start(&mut self) -> &mut Self {
|
pub fn group_start(&mut self) -> &mut Self {
|
||||||
if self.state.query_map.len() == 0 {
|
let conj = if self.state.query_map.len() == 0 {
|
||||||
self.state
|
" WHERE "
|
||||||
.append_query_map(QueryClauseType::GroupStart, " ", "(");
|
|
||||||
} else {
|
} else {
|
||||||
self.state
|
" "
|
||||||
.append_query_map(QueryClauseType::GroupStart, " WHERE ", "(");
|
};
|
||||||
}
|
|
||||||
|
self.state
|
||||||
|
.append_query_map(QueryClauseType::GroupStart, conj, "(");
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start a logical grouping, prefixed with `not`
|
/// Start a logical grouping, prefixed with `not`
|
||||||
pub fn not_group_start(&mut self) -> &mut Self {
|
pub fn not_group_start(&mut self) -> &mut Self {
|
||||||
if self.state.query_map.len() == 0 {
|
let conj = if self.state.query_map.len() == 0 {
|
||||||
self.state
|
" WHERE "
|
||||||
.append_query_map(QueryClauseType::GroupStart, " WHERE NOT ", "(");
|
|
||||||
} else {
|
} else {
|
||||||
self.state
|
" AND "
|
||||||
.append_query_map(QueryClauseType::GroupStart, " AND NOT ", "(");
|
};
|
||||||
}
|
|
||||||
|
self.state
|
||||||
|
.append_query_map(QueryClauseType::GroupStart, conj, "NOT (");
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -491,7 +510,7 @@ impl QueryBuilder {
|
|||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/// Execute the built query
|
/// Execute the built query
|
||||||
pub fn get(self) -> Box<dyn Any> {
|
pub fn get(self) {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -556,7 +575,11 @@ impl QueryBuilder {
|
|||||||
// ! Implementation Details
|
// ! Implementation Details
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
fn compile() -> String {
|
fn compile(&self, query_type: QueryType, table: &str) -> String {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile_type(&self, query_type: QueryType, table: &str) -> String {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user