Skip to content
This repository has been archived by the owner on Jun 6, 2024. It is now read-only.

Commit

Permalink
Merge branch 'main' of https://github.com/cmu-db/15721-s24-catalog1 i…
Browse files Browse the repository at this point in the history
…nto smakhija_repository
  • Loading branch information
SimranMakhija7 committed Mar 14, 2024
2 parents 4d84068 + 3602bdf commit a4dd7bc
Show file tree
Hide file tree
Showing 19 changed files with 327 additions and 8 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PORT=3000
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "rust-rocksdb"]
path = rust-rocksdb
url = https://github.com/rust-rocksdb/rust-rocksdb.git
7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
axum = {version = "0.7.4"}
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1.0", features = ["full"] }
serde_json = "1.0"
tower-http = { version = "0.4.0", features = ["full"] }
dotenv = "0.15.0"
rocksdb = "0.22.0"

pretty_assertions = "0.7"
select = "0.5"
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Catalog Team 1
1 change: 1 addition & 0 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod parameters;
13 changes: 13 additions & 0 deletions src/config/parameters.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use dotenv;

// load the env file
pub fn init() {
dotenv::dotenv().ok().expect("Failed to load .env file");
}

// get the parameters from the env file and throw errors appropriately
pub fn get(parameter: &str) -> String {
let env_parameter = std::env::var(parameter)
.expect(&format!("{} is not defined in the environment", parameter));
env_parameter
}
11 changes: 11 additions & 0 deletions src/dto/column_data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use serde::{Deserialize, Serialize};
use serde_json::Value;

#[derive(Debug, Serialize, Deserialize)]
pub struct ColumnData {
pub aggregates: Value,
pub value_range: (i32, i32),
pub is_strong_key: bool,
pub is_weak_key: bool,
pub primary_key_col_name: String,
}
1 change: 1 addition & 0 deletions src/dto/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod column_data;
pub mod namespace_data;
pub mod operator_statistics;
pub mod table_data;
8 changes: 2 additions & 6 deletions src/dto/table_data.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::dto::column_data::ColumnData;
use serde::{Deserialize, Serialize};
use serde_json::Value;

Expand All @@ -8,10 +9,5 @@ pub struct TableData {
pub read_properties: Value,
pub write_properties: Value,
pub file_urls: Vec<String>,
pub columns: Vec<Vec<String>>,
pub aggregates: Value,
pub value_range: (i32, i32),
pub is_strong_key: bool,
pub is_weak_key: bool,
pub primary_key_col_name: String,
pub columns: Vec<ColumnData>,
}
2 changes: 2 additions & 0 deletions src/handlers/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod namespace_handler;
pub mod table_handler;
73 changes: 73 additions & 0 deletions src/handlers/namespace_handler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use axum::{
extract::{Json, Path},
http::StatusCode,
response::IntoResponse,
};

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct Namespace {}

pub async fn list_namespaces() -> Json<Vec<String>> {
// Logic to list namespaces
let namespaces: Vec<String> = vec![
"accounting".to_string(),
"tax".to_string(),
"paid".to_string(),
];
Json(namespaces)
}

pub async fn create_namespace(new_namespace: Json<Namespace>) -> Json<Namespace> {
// Logic to create a new namespace

// Logic to persist the namespace and add properties
new_namespace
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct NamespaceMetadata {
// Define your namespace metadata properties here
// Example: pub metadata_property: String,
data: String,
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct NamespaceProperties {
data: String,
}

pub async fn load_namespace_metadata(Path(namespace): Path<String>) -> Json<NamespaceMetadata> {
print!("Namespaces: {}", namespace);
// Logic to load metadata properties for a namespace
let metadata = NamespaceMetadata {
data: namespace,
// Populate with actual metadata properties
};
Json(metadata)
}

pub async fn namespace_exists(Path(namespace): Path<String>) -> impl IntoResponse {
// Logic to check if a namespace exists
// This route just needs to return a status code, no body required
// Return HTTP status code 200 to indicate namespace exists
StatusCode::FOUND
}

pub async fn drop_namespace(Path(namespace): Path<String>) -> impl IntoResponse {
// Logic to drop a namespace from the catalog
// Ensure the namespace is empty before dropping
// Return HTTP status code 204 to indicate successful deletion
StatusCode::NO_CONTENT
}

pub async fn set_namespace_properties(Path(namespace): Path<String>) -> Json<NamespaceProperties> {
// Logic to set and/or remove properties on a namespace
// Deserialize request body and process properties
// Return HTTP status code 200 to indicate success

let prop = NamespaceProperties {
data: "namespace properties".to_string(),
};

Json(prop)
}
64 changes: 64 additions & 0 deletions src/handlers/table_handler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use axum::{
extract::{Json, Path},
http::StatusCode,
response::IntoResponse,
};

pub async fn list_tables(Path(namespace): Path<String>) -> Json<Vec<String>> {
// Dummy response for demonstration
let tables: Vec<String> = vec![
"accounting".to_string(),
"tax".to_string(),
"paid".to_string(),
];
Json(tables)
}

pub async fn create_table(Path(namespace): Path<String>) -> impl IntoResponse {
// Logic to create a table in the given namespace
"Table created".to_string()
}

pub async fn register_table(Path(namespace): Path<String>) -> impl IntoResponse {
// Logic to register a table in the given namespace using metadata file location
"Table registered".to_string()
}

pub async fn load_table(Path((namespace, table)): Path<(String, String)>) -> impl IntoResponse {
// Logic to load a table from the catalog
Json(table)
}

pub async fn delete_table(Path((namespace, table)): Path<(String, String)>) -> impl IntoResponse {
// Logic to drop a table from the catalog
"Table dropped".to_string()
}

pub async fn table_exists(Path((namespace, table)): Path<(String, String)>) -> impl IntoResponse {
// Logic to check if a table exists within a given namespace
StatusCode::OK
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct MetricsReport {}

// Handler functions
pub async fn rename_table(table_rename: String) -> impl IntoResponse {
// Logic to rename a table from its current name to a new name
"Table renamed".to_string()
}

pub async fn report_metrics(Path((namespace, table)): Path<(String, String)>) -> impl IntoResponse {
// Logic to process metrics report
Json(table)
}

pub async fn find_tuple_location(
Path((namespace, table, tuple_id)): Path<(String, String, String)>,
) -> impl IntoResponse {
// Logic to return the physical file location for a given tuple ID
format!(
"Physical file location for tuple ID {} of table {} in namespace {}.",
tuple_id, table, namespace
)
}
18 changes: 16 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
fn main() {
println!("hello world!");
mod config;
mod dto;
mod handlers;
mod routes;
mod tests;

use crate::config::parameters;

#[tokio::main]
async fn main() {
parameters::init();
let host = format!("0.0.0.0:{}", parameters::get("PORT"));

let listener = tokio::net::TcpListener::bind(host).await.unwrap();
let app = routes::root::routes();
axum::serve(listener, app).await.unwrap();
}
3 changes: 3 additions & 0 deletions src/routes/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod namespace;
pub mod root;
pub mod table;
28 changes: 28 additions & 0 deletions src/routes/namespace.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use crate::handlers::namespace_handler;
use axum::{
routing::{delete, get, head, post},
Router,
};

pub fn routes() -> Router {
let router = Router::new()
.route("/namespaces", get(namespace_handler::list_namespaces))
.route("/namespaces", post(namespace_handler::create_namespace))
.route(
"/namespace/:namespace",
get(namespace_handler::load_namespace_metadata),
)
.route(
"/namespace/:namespace",
head(namespace_handler::namespace_exists),
)
.route(
"/namespace/:namespace",
delete(namespace_handler::drop_namespace),
)
.route(
"/namespace/:namespace/properties",
post(namespace_handler::set_namespace_properties),
);
return router;
}
13 changes: 13 additions & 0 deletions src/routes/root.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use crate::routes::{namespace, table};
use axum::routing::IntoMakeService;
use axum::Router;
use tower_http::trace::TraceLayer;

pub fn routes() -> Router {
// merge the 2 routes
let app_router = Router::new()
.nest("/", table::routes())
.nest("/", namespace::routes());

app_router
}
44 changes: 44 additions & 0 deletions src/routes/table.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use crate::handlers::table_handler;
use axum::{
routing::{delete, get, head, post},
Router,
};

pub fn routes() -> Router {
let router = Router::new()
.route(
"/namespaces/:namespace/tables",
get(table_handler::list_tables),
)
.route(
"/namespaces/:namespace/tables",
post(table_handler::create_table),
)
.route(
"/namespaces/:namespace/register",
post(table_handler::register_table),
)
.route(
"/namespaces/:namespace/tables/:table",
get(table_handler::load_table),
)
.route(
"/namespaces/:namespace/tables/:table",
delete(table_handler::delete_table),
)
.route(
"/namespaces/:namespace/tables/:table",
head(table_handler::table_exists),
)
.route("/tables/rename", post(table_handler::rename_table))
.route(
"/namespaces/:namespace/tables/:table/metrics",
post(table_handler::report_metrics),
)
.route(
"/namespaces/:namespace/tables/:table/find/:tuple_id",
get(table_handler::find_tuple_location),
);

return router;
}
1 change: 1 addition & 0 deletions src/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

43 changes: 43 additions & 0 deletions src/tests/namespace_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use axum::{http::StatusCode, response::Json};
use axum::extract::Json as JsonExtractor;
use axum::handler::post;
use axum::routing::Router;
use serde_json::json;
use axum::test::extract;

use crate::{create_namespace, list_namespaces, Namespace};

#[tokio::test]
async fn test_list_namespaces() {
// Create a test router with the list_namespaces route
let app = Router::new().route("/namespaces", post(list_namespaces));

// Perform a request to the route
let response = axum::test::call(&app, axum::test::request::Request::post("/namespaces").body(()).unwrap()).await;

// Ensure that the response status code is OK
assert_eq!(response.status(), StatusCode::OK);

// Ensure that the response body contains the expected JSON data
let body = extract::<Json<Vec<String>>>(response.into_body()).await.unwrap();
assert_eq!(body.0, vec!["accounting", "tax", "paid"]);
}

#[tokio::test]
async fn test_create_namespace() {
// Create a test router with the create_namespace route
let app = Router::new().route("/namespaces", post(create_namespace));

// Create a JSON payload representing a new namespace
let payload = json!({});

// Perform a request to the route with the JSON payload
let response = axum::test::call(&app, axum::test::request::Request::post("/namespaces").body(payload.to_string()).unwrap()).await;

// Ensure that the response status code is OK
assert_eq!(response.status(), StatusCode::OK);

// Ensure that the response body contains the expected JSON data
let body = extract::<Json<Namespace>>(response.into_body()).await.unwrap();
assert_eq!(body, Json(Namespace {}));
}

0 comments on commit a4dd7bc

Please sign in to comment.