Add a rudimentary SQL builder, based on parts of Diesel. (#273) r=nalexander

https://github.com/diesel-rs/diesel/
This commit is contained in:
Richard Newman 2017-02-16 15:07:52 -08:00
parent bc2b2ec4c8
commit f890995202
4 changed files with 92 additions and 0 deletions

View file

@ -35,6 +35,9 @@ path = "parser-utils"
[dependencies.mentat_core]
path = "core"
[dependencies.mentat_sql]
path = "sql"
[dependencies.mentat_db]
path = "db"

3
sql/Cargo.toml Normal file
View file

@ -0,0 +1,3 @@
[package]
name = "mentat_sql"
version = "0.0.1"

7
sql/README.md Normal file
View file

@ -0,0 +1,7 @@
This is a tiny SQL query builder.
The majority of this code was distilled from QueryBuilder in Diesel:
https://github.com/diesel-rs/diesel/
used under the Apache 2.0 license.

79
sql/src/lib.rs Normal file
View file

@ -0,0 +1,79 @@
// Copyright 2016 Mozilla
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
use std::error::Error;
pub type BuildQueryError = Box<Error + Send + Sync>;
pub type BuildQueryResult = Result<(), BuildQueryError>;
/// Gratefully based on Diesel's QueryBuilder trait:
/// https://github.com/diesel-rs/diesel/blob/4885f61b8205f7f3c2cfa03837ed6714831abe6b/diesel/src/query_builder/mod.rs#L56
pub trait QueryBuilder {
fn push_sql(&mut self, sql: &str);
fn push_identifier(&mut self, identifier: &str) -> BuildQueryResult;
fn push_bind_param(&mut self);
fn finish(self) -> String;
}
pub trait QueryFragment {
fn push_sql(&self, out: &mut QueryBuilder) -> BuildQueryResult;
}
impl QueryFragment for Box<QueryFragment> {
fn push_sql(&self, out: &mut QueryBuilder) -> BuildQueryResult {
QueryFragment::push_sql(&**self, out)
}
}
impl<'a> QueryFragment for &'a QueryFragment {
fn push_sql(&self, out: &mut QueryBuilder) -> BuildQueryResult {
QueryFragment::push_sql(&**self, out)
}
}
impl QueryFragment for () {
fn push_sql(&self, _out: &mut QueryBuilder) -> BuildQueryResult {
Ok(())
}
}
/// A QueryBuilder that implements SQLite's specific escaping rules.
pub struct SQLiteQueryBuilder {
pub sql: String,
}
impl SQLiteQueryBuilder {
pub fn new() -> Self {
SQLiteQueryBuilder {
sql: String::new(),
}
}
}
impl QueryBuilder for SQLiteQueryBuilder {
fn push_sql(&mut self, sql: &str) {
self.sql.push_str(sql);
}
fn push_identifier(&mut self, identifier: &str) -> BuildQueryResult {
self.push_sql("`");
self.push_sql(&identifier.replace("`", "``"));
self.push_sql("`");
Ok(())
}
fn push_bind_param(&mut self) {
self.push_sql("?");
}
fn finish(self) -> String {
self.sql
}
}