From 4e2b39993e2b185f745ab22817114e152e4e8a37 Mon Sep 17 00:00:00 2001 From: Harsh Singh Date: Mon, 23 Oct 2023 12:18:47 +0530 Subject: [PATCH] sql processor --- fastn-core/src/library2022/mod.rs | 11 ++++- fastn-core/src/library2022/processor/pg.rs | 4 +- fastn-core/src/library2022/processor/sql.rs | 34 +++++++++++++ .../src/library2022/processor/sqlite.rs | 49 ++++++------------- 4 files changed, 62 insertions(+), 36 deletions(-) diff --git a/fastn-core/src/library2022/mod.rs b/fastn-core/src/library2022/mod.rs index 3d9182cff1..f008c11cb6 100644 --- a/fastn-core/src/library2022/mod.rs +++ b/fastn-core/src/library2022/mod.rs @@ -279,7 +279,16 @@ impl Library2022 { "user-details" => processor::user_details::process(value, kind, doc, &self.config), "fastn-apps" => processor::apps::process(value, kind, doc, &self.config), "is-reader" => processor::user_group::is_reader(value, kind, doc, &self.config).await, - "package-query" => processor::sqlite::process(value, kind, doc, &self.config).await, + "sql" => processor::sql::process(value, kind, doc).await, + "package-query" => { + processor::sqlite::process( + value, + kind, + doc, + &fastn_core::library2022::processor::sql::get_db_config()?, + ) + .await + } "pg" => processor::pg::process(value, kind, doc).await, "package-tree" => { processor::package_tree::process(value, kind, doc, &self.config).await diff --git a/fastn-core/src/library2022/processor/pg.rs b/fastn-core/src/library2022/processor/pg.rs index a9c0aa658b..a3c5162aab 100644 --- a/fastn-core/src/library2022/processor/pg.rs +++ b/fastn-core/src/library2022/processor/pg.rs @@ -1,9 +1,9 @@ async fn create_pool() -> Result { let mut cfg = deadpool_postgres::Config::new(); - cfg.libpq_style_connection_string = match std::env::var("FASTN_PG_URL") { + cfg.libpq_style_connection_string = match std::env::var("FASTN_DB_URL") { Ok(v) => Some(v), Err(_) => { - fastn_core::warning!("FASTN_PG_URL is not set"); + fastn_core::warning!("FASTN_DB_URL is not set"); return Err(deadpool_postgres::CreatePoolError::Config( deadpool_postgres::ConfigError::ConnectionStringInvalid, )); diff --git a/fastn-core/src/library2022/processor/sql.rs b/fastn-core/src/library2022/processor/sql.rs index 4afd1346d8..7742353b5d 100644 --- a/fastn-core/src/library2022/processor/sql.rs +++ b/fastn-core/src/library2022/processor/sql.rs @@ -1,3 +1,37 @@ +#[derive(Debug)] +pub struct DatabaseConfig { + pub db_url: String, + pub db_type: String, +} + +pub(crate) fn get_db_config() -> ftd::interpreter::Result { + let db_url = std::env::var("FASTN_DB_URL").expect("FASTN_DB_URL is not set"); + let url = url::Url::parse(&db_url).expect("Invalid DB Url"); + let db_type = url.scheme().to_string(); + + let config = DatabaseConfig { db_url, db_type }; + + Ok(config) +} + +pub async fn process( + value: ftd::ast::VariableValue, + kind: ftd::interpreter::Kind, + doc: &ftd::interpreter::TDoc<'_>, +) -> ftd::interpreter::Result { + let db_config = fastn_core::library2022::processor::sql::get_db_config()?; + let db_type = db_config.db_type.as_str(); + + match db_type { + "pg" => Ok(fastn_core::library2022::processor::pg::process(value, kind, doc).await?), + "sqlite" => Ok(fastn_core::library2022::processor::sqlite::process( + value, kind, doc, &db_config, + ) + .await?), + _ => unimplemented!("Database currently not supported."), + } +} + pub const STATUS_OK: usize = 0; pub const STATUS_ERROR: usize = 1; const BACKSLASH: char = '\\'; diff --git a/fastn-core/src/library2022/processor/sqlite.rs b/fastn-core/src/library2022/processor/sqlite.rs index e243bed728..7d300042fb 100644 --- a/fastn-core/src/library2022/processor/sqlite.rs +++ b/fastn-core/src/library2022/processor/sqlite.rs @@ -28,33 +28,10 @@ pub async fn process( value: ftd::ast::VariableValue, kind: ftd::interpreter::Kind, doc: &ftd::interpreter::TDoc<'_>, - config: &fastn_core::Config, + db_config: &fastn_core::library2022::processor::sql::DatabaseConfig, ) -> ftd::interpreter::Result { let (headers, query) = get_p1_data("package-data", &value, doc.name)?; - let sqlite_database = - match headers.get_optional_string_by_key("db", doc.name, value.line_number())? { - Some(k) => k, - None => { - return ftd::interpreter::utils::e2( - "`db` is not specified".to_string(), - doc.name, - value.line_number(), - ) - } - }; - let mut sqlite_database_path = camino::Utf8PathBuf::new().join(sqlite_database.as_str()); - if !sqlite_database_path.exists() { - if !config.root.join(sqlite_database_path.as_path()).exists() { - return ftd::interpreter::utils::e2( - "`db` does not exists for package-query processor".to_string(), - doc.name, - value.line_number(), - ); - } - sqlite_database_path = config.root.join(sqlite_database_path.as_path()); - } - // need the query params // question is they can be multiple // so lets say start with passing attributes from ftd file @@ -64,7 +41,7 @@ pub async fn process( // select * from users where let query_response = execute_query( - &sqlite_database_path, + db_config.db_url.as_str(), query.as_str(), doc, headers, @@ -203,18 +180,24 @@ fn extract_named_parameters( let mut inside_type_hint = false; for c in query.chars() { - if c == ':' && !inside_param { + if c == '$' && !inside_param { inside_param = true; param_name.clear(); param_type.clear(); inside_type_hint = false; } else if c == ':' && inside_param { - inside_type_hint = true; - } else if c.is_alphanumeric() && inside_param && !inside_type_hint { - param_name.push(c); - } else if c.is_alphanumeric() && inside_param && inside_type_hint { - param_type.push(c); - } else if inside_param && (c == ',' || c.is_whitespace()) && !param_name.is_empty() { + if inside_type_hint { + param_type.push(c); + } else { + inside_type_hint = true; + } + } else if c.is_alphanumeric() && inside_param { + if inside_type_hint { + param_type.push(c); + } else { + param_name.push(c); + } + } else if c == ',' || c.is_whitespace() && !param_name.is_empty() { inside_param = false; inside_type_hint = false; @@ -255,7 +238,7 @@ fn extract_named_parameters( } async fn execute_query( - database_path: &camino::Utf8Path, + database_path: &str, query: &str, doc: &ftd::interpreter::TDoc<'_>, headers: ftd::ast::HeaderValues,