diff --git a/query-translator/src/lib.rs b/query-translator/src/lib.rs index 7c18b962..3a0e0050 100644 --- a/query-translator/src/lib.rs +++ b/query-translator/src/lib.rs @@ -16,6 +16,10 @@ extern crate mentat_sql; mod translate; mod types; +pub use types::{ + Projection, +}; + pub use translate::{ cc_to_exists, cc_to_select, diff --git a/src/errors.rs b/src/errors.rs index 8594172b..359072ce 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -15,6 +15,7 @@ use rusqlite; use edn; use mentat_db; use mentat_query_parser; +use mentat_sql; use mentat_tx_parser; error_chain! { @@ -30,6 +31,14 @@ error_chain! { links { DbError(mentat_db::Error, mentat_db::ErrorKind); QueryParseError(mentat_query_parser::Error, mentat_query_parser::ErrorKind); + SqlError(mentat_sql::Error, mentat_sql::ErrorKind); TxParseError(mentat_tx_parser::Error, mentat_tx_parser::ErrorKind); } + + errors { + InvalidArgumentName(name: String) { + description("invalid argument name") + display("invalid argument name: '{}'", name) + } + } } diff --git a/src/lib.rs b/src/lib.rs index d5c362cd..bf635254 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,8 +10,10 @@ #[macro_use] extern crate error_chain; + #[macro_use] extern crate slog; + #[macro_use] extern crate slog_scope; @@ -21,8 +23,10 @@ extern crate edn; extern crate mentat_core; extern crate mentat_db; extern crate mentat_query; -extern crate mentat_query_parser; extern crate mentat_query_algebrizer; +extern crate mentat_query_parser; +extern crate mentat_query_translator; +extern crate mentat_sql; extern crate mentat_tx_parser; use rusqlite::Connection; diff --git a/src/query.rs b/src/query.rs index d8bd4064..25a7cb57 100644 --- a/src/query.rs +++ b/src/query.rs @@ -11,21 +11,28 @@ use std::collections::HashMap; use mentat_core::{ + Schema, TypedValue, }; -use mentat_db::DB; +use mentat_query_algebrizer::algebrize; use mentat_query_parser::{ parse_find_string, }; -use errors::{ - Result, +use mentat_sql::{ + SQLQuery, }; -// TODO -pub type SQLiteConnection = (); +use mentat_query_translator::{ + cc_to_select, + Projection, +}; + +use errors::Result; + +use rusqlite; pub enum QueryResults { Scalar(Option), @@ -34,17 +41,39 @@ pub enum QueryResults { Rel(Vec>), } +pub type QueryExecutionResult = Result; + /// Take an EDN query string, a reference to a open SQLite connection, a Mentat DB, and an optional /// collection of input bindings (which should be keyed by `"?varname"`), and execute the query /// immediately, blocking the current thread. /// Returns a structure that corresponds to the kind of input query, populated with `TypedValue` /// instances. +/// The caller is responsible for ensuring that the SQLite connection is in a transaction if +/// isolation is required. #[allow(unused_variables)] -pub fn q_once(sqlite: SQLiteConnection, - db: DB, - query: &str, - inputs: Option>) -> Result { +pub fn q_once<'sqlite, 'schema, 'query> +(sqlite: &'sqlite rusqlite::Connection, + schema: &'schema Schema, + query: &'query str, + inputs: Option>) -> QueryExecutionResult { // TODO: validate inputs. let parsed = parse_find_string(query)?; + let algebrized = algebrize(schema, parsed); + let projection = Projection::Star; + let select = cc_to_select(projection, algebrized.cc); + let SQLQuery { sql, args } = select.to_sql_query()?; + + /* + let mut statement = sqlite.prepare(sql.as_str())?; + + let mut rows = if args.is_empty() { + statement.query(&[])? + } else { + statement.query_named(args.map(|(k, v)| (k.as_str(), &v)))? + }; + */ + + + Ok(QueryResults::Scalar(Some(TypedValue::Boolean(true)))) }