Skip to content

Commit

Permalink
Merge pull request #536 from prisma/do-not-panic-on-empty-sqlite-url
Browse files Browse the repository at this point in the history
Return a known error on invalid/absent database string
  • Loading branch information
tomhoule committed Feb 26, 2020
2 parents d49ab93 + ead4805 commit 6cf3607
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 28 deletions.
6 changes: 6 additions & 0 deletions libs/user-facing-errors/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,12 @@ pub struct SchemaParserError {
pub full_error: String,
}

#[derive(Debug, UserFacingError, Serialize)]
#[user_facing(code = "P1013", message = "The provided database string is invalid. ${details}")]
pub struct InvalidDatabaseString {
pub details: String,
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
7 changes: 7 additions & 0 deletions libs/user-facing-errors/src/quaint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,13 @@ pub fn render_quaint_error(kind: &ErrorKind, connection_info: &ConnectionInfo) -
.ok()
}

(ErrorKind::DatabaseUrlIsInvalid(details), _connection_info) => {
KnownError::new(common::InvalidDatabaseString {
details: details.to_owned(),
})
.ok()
}

_ => None,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub use sqlite::*;

#[async_trait]
pub trait FromSource {
async fn from_source(source: &dyn Source) -> crate::Result<Self>
async fn from_source(source: &dyn Source) -> connector_interface::Result<Self>
where
Self: Connector + Sized;
}
Expand Down
19 changes: 14 additions & 5 deletions query-engine/connectors/sql-query-connector/src/database/mysql.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
use super::connection::SqlConnection;
use crate::{query_builder::ManyRelatedRecordsWithUnionAll, FromSource, SqlError};
use async_trait::async_trait;
use connector_interface::{Connection, Connector, IO};
use connector_interface::{
error::{ConnectorError, ErrorKind},
Connection, Connector, IO,
};
use datamodel::Source;
use quaint::pooled::Quaint;
use quaint::{pooled::Quaint, prelude::ConnectionInfo};

pub struct Mysql {
pool: Quaint,
connection_info: quaint::prelude::ConnectionInfo,
connection_info: ConnectionInfo,
}

#[async_trait]
impl FromSource for Mysql {
async fn from_source(source: &dyn Source) -> crate::Result<Self> {
let pool = Quaint::new(&source.url().value).await?;
async fn from_source(source: &dyn Source) -> connector_interface::Result<Self> {
let connection_info = ConnectionInfo::from_url(&source.url().value)
.map_err(|err| ConnectorError::from_kind(ErrorKind::ConnectionError(err.into())))?;

let pool = Quaint::new(&source.url().value)
.await
.map_err(SqlError::from)
.map_err(|sql_error| sql_error.into_connector_error(&connection_info))?;
let connection_info = pool.connection_info().to_owned();
Ok(Mysql { pool, connection_info })
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
use super::connection::SqlConnection;
use crate::{query_builder::ManyRelatedRecordsWithRowNumber, FromSource, SqlError};
use async_trait::async_trait;
use connector_interface::{Connection, Connector, IO};
use connector_interface::{
error::{ConnectorError, ErrorKind},
Connection, Connector, IO,
};
use datamodel::Source;
use quaint::pooled::Quaint;
use quaint::{pooled::Quaint, prelude::ConnectionInfo};

pub struct PostgreSql {
pool: Quaint,
connection_info: quaint::prelude::ConnectionInfo,
connection_info: ConnectionInfo,
}

#[async_trait]
impl FromSource for PostgreSql {
async fn from_source(source: &dyn Source) -> crate::Result<Self> {
let pool = Quaint::new(&source.url().value).await?;
async fn from_source(source: &dyn Source) -> connector_interface::Result<Self> {
let connection_info = ConnectionInfo::from_url(&source.url().value)
.map_err(|err| ConnectorError::from_kind(ErrorKind::ConnectionError(err.into())))?;

let pool = Quaint::new(&source.url().value)
.await
.map_err(SqlError::from)
.map_err(|sql_error| sql_error.into_connector_error(&connection_info))?;
let connection_info = pool.connection_info().to_owned();
Ok(PostgreSql { pool, connection_info })
}
Expand Down
34 changes: 26 additions & 8 deletions query-engine/connectors/sql-query-connector/src/database/sqlite.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use super::connection::SqlConnection;
use crate::{query_builder::ManyRelatedRecordsWithRowNumber, FromSource, SqlError};
use async_trait::async_trait;
use connector_interface::{Connection, Connector, IO};
use connector_interface::{
error::{ConnectorError, ErrorKind},
Connection, Connector, IO,
};
use datamodel::Source;
use quaint::{connector::SqliteParams, pooled::Quaint, prelude::ConnectionInfo};
use quaint::{connector::SqliteParams, error::ErrorKind as QuaintKind, pooled::Quaint, prelude::ConnectionInfo};
use std::convert::TryFrom;

pub struct Sqlite {
Expand All @@ -23,17 +26,21 @@ impl Sqlite {

#[async_trait]
impl FromSource for Sqlite {
async fn from_source(source: &dyn Source) -> crate::Result<Sqlite> {
let params = SqliteParams::try_from(source.url().value.as_str())?;
async fn from_source(source: &dyn Source) -> connector_interface::Result<Sqlite> {
let connection_info = ConnectionInfo::from_url(&source.url().value)
.map_err(|err| ConnectorError::from_kind(ErrorKind::ConnectionError(err.into())))?;

let params = SqliteParams::try_from(source.url().value.as_str())
.map_err(SqlError::from)
.map_err(|sql_error| sql_error.into_connector_error(&connection_info))?;

let file_path = params.file_path;

let url_with_db = {
let db_name = std::path::Path::new(&file_path)
.file_stem()
.unwrap()
.to_str()
.unwrap()
.and_then(|stem| stem.to_str())
.ok_or_else(|| invalid_file_path_error(&file_path, &connection_info))?
.to_owned();

let mut splitted = source.url().value.split("?");
Expand All @@ -51,12 +58,23 @@ impl FromSource for Sqlite {
format!("{}?{}", url, params.join("&"))
};

let pool = Quaint::new(url_with_db.as_str()).await?;
let pool = Quaint::new(url_with_db.as_str())
.await
.map_err(SqlError::from)
.map_err(|sql_error| sql_error.into_connector_error(&connection_info))?;

Ok(Sqlite { pool, file_path })
}
}

fn invalid_file_path_error(file_path: &str, connection_info: &ConnectionInfo) -> ConnectorError {
SqlError::ConnectionError(QuaintKind::DatabaseUrlIsInvalid(format!(
"\"{}\" is not a valid sqlite file path",
file_path
)))
.into_connector_error(&connection_info)
}

impl Connector for Sqlite {
fn get_connection<'a>(&'a self) -> IO<Box<dyn Connection + 'a>> {
IO::new(super::catch(&self.connection_info(), async move {
Expand Down
22 changes: 13 additions & 9 deletions query-engine/prisma/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
use connector::error::ConnectorError;
use datamodel::error::ErrorCollection;
use failure::{Error, Fail};
use graphql_parser::query::ParseError as GqlParseError;
use query_core::{response_ir, CoreError};
use serde_json;

#[cfg(feature = "sql")]
use sql_connector::SqlError;

#[derive(Debug, Fail)]
pub enum PrismaError {
#[fail(display = "{}", _0)]
Expand All @@ -21,6 +19,9 @@ pub enum PrismaError {
#[fail(display = "{}", _0)]
ConfigurationError(String),

#[fail(display = "{}", _0)]
ConnectorError(ConnectorError),

#[fail(display = "{}", _0)]
ConversionError(ErrorCollection, String),

Expand All @@ -42,13 +43,17 @@ pub enum PrismaError {
}

impl PrismaError {
pub(crate) fn render_as_json(&self) -> Result<(), failure::Error> {
pub(crate) fn render_as_json(self) -> Result<(), failure::Error> {
use std::fmt::Write as _;
use std::io::Write as _;

let error: user_facing_errors::Error = match self {
PrismaError::ConnectorError(ConnectorError {
user_facing_error: Some(err),
..
}) => err.into(),
PrismaError::ConversionError(errors, dml_string) => {
let mut full_error = errors.to_pretty_string("schema.prisma", dml_string);
let mut full_error = errors.to_pretty_string("schema.prisma", &dml_string);
write!(full_error, "\nValidation Error Count: {}", errors.to_iter().len())?;

user_facing_errors::Error::from(
Expand Down Expand Up @@ -129,9 +134,8 @@ impl From<GqlParseError> for PrismaError {
}
}

#[cfg(feature = "sql")]
impl From<SqlError> for PrismaError {
fn from(e: SqlError) -> PrismaError {
PrismaError::ConfigurationError(format!("{}", e))
impl From<ConnectorError> for PrismaError {
fn from(e: ConnectorError) -> PrismaError {
PrismaError::ConnectorError(e)
}
}

0 comments on commit 6cf3607

Please sign in to comment.