diff --git a/crates/torii/server/src/handlers/sql.rs b/crates/torii/server/src/handlers/sql.rs index 2d48b20d07..95004a52da 100644 --- a/crates/torii/server/src/handlers/sql.rs +++ b/crates/torii/server/src/handlers/sql.rs @@ -4,6 +4,7 @@ use base64::engine::general_purpose::STANDARD; use base64::Engine; use http::header::CONTENT_TYPE; use hyper::{Body, Method, Request, Response, StatusCode}; +use include_str; use sqlx::{Column, Row, SqlitePool, TypeInfo}; use super::Handler; @@ -29,7 +30,7 @@ impl SqlHandler { "TEXT" => row .get::, _>(i) .map_or(serde_json::Value::Null, serde_json::Value::String), - "INTEGER" | "NULL" => row + "INTEGER" => row .get::, _>(i) .map_or(serde_json::Value::Null, |n| { serde_json::Value::Number(n.into()) @@ -48,9 +49,25 @@ impl SqlHandler { .map_or(serde_json::Value::Null, |bytes| { serde_json::Value::String(STANDARD.encode(bytes)) }), - _ => row - .get::, _>(i) - .map_or(serde_json::Value::Null, serde_json::Value::String), + _ => { + // Try different types in order + if let Ok(val) = row.try_get::(i) { + serde_json::Value::Number(val.into()) + } else if let Ok(val) = row.try_get::(i) { + // Handle floating point numbers + serde_json::json!(val) + } else if let Ok(val) = row.try_get::(i) { + serde_json::Value::Bool(val) + } else if let Ok(val) = row.try_get::(i) { + serde_json::Value::String(val) + } else { + // Handle or fallback to BLOB as base64 + let val = row.get::>, _>(i); + val.map_or(serde_json::Value::Null, |bytes| { + serde_json::Value::String(STANDARD.encode(bytes)) + }) + } + } }; obj.insert(column.name().to_string(), value); } @@ -117,6 +134,28 @@ impl SqlHandler { .unwrap()), } } + + async fn serve_playground(&self) -> Response { + let html = include_str!("../../static/sql-playground.html"); + + Response::builder() + .status(StatusCode::OK) + .header(CONTENT_TYPE, "text/html") + .header("Access-Control-Allow-Origin", "*") + .body(Body::from(html)) + .unwrap() + } + + async fn handle_request(&self, req: Request) -> Response { + if req.method() == Method::GET && req.uri().query().unwrap_or_default().is_empty() { + self.serve_playground().await + } else { + match self.extract_query(req).await { + Ok(query) => self.execute_query(query).await, + Err(_) => self.serve_playground().await, + } + } + } } #[async_trait::async_trait] @@ -126,9 +165,6 @@ impl Handler for SqlHandler { } async fn handle(&self, req: Request) -> Response { - match self.extract_query(req).await { - Ok(query) => self.execute_query(query).await, - Err(response) => response, - } + self.handle_request(req).await } } diff --git a/crates/torii/server/static/sql-playground.html b/crates/torii/server/static/sql-playground.html new file mode 100644 index 0000000000..52f7f0c65a --- /dev/null +++ b/crates/torii/server/static/sql-playground.html @@ -0,0 +1,925 @@ + + + + + + Torii SQL Playground + + + + + + + +
+ + +