commit 505bf8bf6de65cc8b05b545bb0961901beb99b89 Author: Timothy Warren Date: Tue Apr 2 14:36:11 2019 -0400 First commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e6350fc --- /dev/null +++ b/.gitignore @@ -0,0 +1,132 @@ + +# Created by https://www.gitignore.io/api/rust,macos,jetbrains+all +# Edit at https://www.gitignore.io/?templates=rust,macos,jetbrains+all + +### JetBrains+all ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +# JetBrains templates +**___jb_tmp___ + +### JetBrains+all Patch ### +# Ignores the whole .idea folder and all .iml files +# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 + +.idea/ + +# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 + +*.iml +modules.xml +.idea/misc.xml +*.ipr + +# Sonarlint plugin +.idea/sonarlint + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Rust ### +# Generated by Cargo +# will have compiled files and executables +/target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk + +# End of https://www.gitignore.io/api/rust,macos,jetbrains+all diff --git a/.project b/.project new file mode 100644 index 0000000..90bfc96 --- /dev/null +++ b/.project @@ -0,0 +1,11 @@ + + + stringqb + + + + + + + + diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..acb3b10 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "stringqb" +version = "0.1.0" +authors = ["Timothy Warren "] +edition = "2018" +categories = ["database"] + +[dependencies] +serde_json = "1.0.39" + +[dependencies.postgres] +version="0.15.2" +features=["with-serde_json"] +optional=true + +[dependencies.rusqlite] +version="0.17.0" +features=["chrono","serde_json","url"] +optional=true \ No newline at end of file diff --git a/src/drivers.rs b/src/drivers.rs new file mode 100644 index 0000000..d03e369 --- /dev/null +++ b/src/drivers.rs @@ -0,0 +1,20 @@ +pub trait DatabaseDriver { + fn query(&self, query: &str) -> Result<(), ()>; +} + +pub struct Postgres; +pub struct SQLite; + + +impl DatabaseDriver for Postgres { + fn query(&self, _query: &str) -> Result<(), ()> { + Ok(()) + } +} + +impl DatabaseDriver for SQLite { + fn query(&self, _query: &str) -> Result<(), ()> { + Ok(()) + } +} + diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..987e0c6 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,6 @@ +/// # StringQB +/// +/// A query builder using mostly strings, with methods following common SQL syntax + +mod drivers; +mod query_builder; diff --git a/src/query_builder.rs b/src/query_builder.rs new file mode 100644 index 0000000..508db1c --- /dev/null +++ b/src/query_builder.rs @@ -0,0 +1,97 @@ +use std::any::Any; +use std::collections::HashMap; + +use crate::drivers::DatabaseDriver; + +#[derive(Debug)] +enum QueryClauseType { + AndGroupStart, + GroupEnd, + GroupStart, + Like, + OrGroupStart, + Where, + WhereIn, +} + +#[derive(Debug)] +struct QueryClause { + clause_type: QueryClauseType, + conjunction: String, + string: String, +} + +#[derive(Default, Debug)] +struct QueryState { + select_string: String, + from_string: String, + set_string: String, + order_string: String, + group_string: String, + + // Keys for insert/update statement + pub set_array_keys: Vec, + + // Order by clause + order_array: HashMap, + + // Group by clause + group_array: HashMap, + + // Values to apply to prepared statements + pub values: Vec, + + // Values to apply to where clauses in prepared statements + pub where_values: Vec, + + limit: u32, + + offset: u32, + + // Query components for complex selects + query_map: Vec, + + // Query components for having clauses + having_map: Vec, +} + +impl QueryState { + pub fn new() -> QueryState { + QueryState::default() + } +} + +#[derive(Default, Debug)] +pub struct QueryBuilder { + state: QueryState, + driver: Option, +} + +impl QueryBuilder { + pub fn new() -> QueryBuilder { + QueryBuilder { + state: QueryState::new(), + driver: None, + } + } + + pub fn set(mut self, key: String, value: String) -> Self { + self.state.set_array_keys.push(key); + self.state.values.push(value); + + self + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn set_key_value() { + let builder = QueryBuilder::new(); + let builder = builder.set("foo".to_string(), "bar".to_string()); + + assert_eq!(builder.state.values, vec!["bar"]); + } +} \ No newline at end of file