use crate::request::headers::HeadersTypes;
use crate::{generate_random_id, SupabaseClient};
use reqwest::Response;
use serde_json::{json, Value};
impl SupabaseClient {
pub async fn insert_with_generated_id(
&self,
table_name: &str,
mut body: Value,
) -> Result<String, String> {
let endpoint: String = self.endpoint(table_name);
#[cfg(feature = "nightly")]
use crate::nightly::print_nightly_warning;
#[cfg(feature = "nightly")]
print_nightly_warning();
let new_id: i64 = generate_random_id();
body["id"] = json!(new_id);
let response: Response = match self
.client
.post(&endpoint)
.header(HeadersTypes::ApiKey, &self.api_key)
.header(
HeadersTypes::Authorization,
format!("Bearer {}", &self.api_key),
)
.header(HeadersTypes::ContentType, "application/json")
.header(HeadersTypes::ClientInfo, &crate::client_info())
.header(HeadersTypes::ContentProfile.as_str(), self.schema.as_str())
.body(body.to_string())
.send()
.await
{
Ok(response) => response,
Err(e) => return Err(e.to_string()),
};
if response.status().is_success() {
Ok(new_id.to_string())
} else if response.status().as_u16() == 409 {
println!("\x1b[31mError 409: Duplicate entry. The value you're trying to insert may already exist in a column with a UNIQUE constraint.\x1b[0m");
Err("Error 409: Duplicate entry. The value you're trying to insert may already exist in a column with a UNIQUE constraint.".to_owned())
} else {
println!("\x1b[31mError: {:?}\x1b[0m", response);
Err(response.status().to_string())
}
}
pub async fn insert<T>(&self, table_name: &str, body: T) -> Result<String, String>
where
T: serde::Serialize,
{
let body = match serde_json::to_value(body) {
Ok(v) => v,
Err(e) => return Err(format!("Failed to serialize body: {}", e)),
};
let endpoint: String = self.endpoint(table_name);
#[cfg(feature = "nightly")]
use crate::nightly::print_nightly_warning;
#[cfg(feature = "nightly")]
print_nightly_warning();
let response: Response = match self
.client
.post(&endpoint)
.header(HeadersTypes::ApiKey, &self.api_key)
.header(
HeadersTypes::Authorization,
format!("Bearer {}", &self.api_key),
)
.header(HeadersTypes::ContentType, "application/json")
.header(HeadersTypes::ClientInfo, &crate::client_info())
.header(HeadersTypes::Prefer, "return=representation")
.header(HeadersTypes::ContentProfile.as_str(), self.schema.as_str())
.body(body.to_string())
.send()
.await
{
Ok(response) => response,
Err(e) => return Err(e.to_string()),
};
if response.status().is_success() {
let res_text: String = match response.text().await {
Ok(text) => text,
Err(e) => return Err(format!("Failed to get response text: {}", e)),
};
let id: String = match serde_json::from_str::<Vec<Value>>(&res_text) {
Ok(json) => json[0]["id"].to_string(),
Err(e) => return Err(format!("Failed to parse response text: {}", e)),
};
Ok(id)
} else if response.status().as_u16() == 409 {
println!("\x1b[31mError 409: Duplicate entry. The value you're trying to insert may already exist in a column with a UNIQUE constraint.\x1b[0m");
Err("Error 409: Duplicate entry. The value you're trying to insert may already exist in a column with a UNIQUE constraint.".to_owned())
} else {
println!("\x1b[31mError: {:?}\x1b[0m", response);
Err(response.status().to_string())
}
}
pub async fn insert_without_defined_key<T>(
&self,
table_name: &str,
body: T,
) -> Result<String, String>
where
T: serde::Serialize,
{
self.insert(table_name, body).await
}
pub async fn insert_if_unique<T>(&self, table_name: &str, body: T) -> Result<String, String>
where
T: serde::Serialize + Clone,
{
let body = match serde_json::to_value(body.clone()) {
Ok(v) => v,
Err(e) => return Err(format!("Failed to serialize body: {}", e)),
};
let conditions: &serde_json::Map<String, Value> = match body.as_object() {
Some(map) => map,
None => {
println!("\x1b[31mFailed to parse body as JSON object\x1b[0m");
return Err("Failed to parse body as JSON object".to_owned());
}
};
let mut query: crate::query::QueryBuilder = self.select(table_name);
for (column_name, column_value) in conditions {
let column_value_str: String = match column_value {
Value::String(s) => s.clone(),
Value::Null
| Value::Bool(_)
| Value::Number(_)
| Value::Array(_)
| Value::Object(_) => column_value.to_string(),
};
query = query.eq(column_name, column_value_str.as_str());
}
let response: Result<Vec<Value>, String> = query.execute().await;
if let Ok(results) = response {
if results.is_empty() {
return self.insert(table_name, body).await;
}
} else {
println!("\x1b[31mFailed to execute select query\x1b[0m");
return Err("Failed to execute select query".to_owned());
}
Err("Error 409: Duplicate entry. The values you're trying to insert may already exist in a column with a UNIQUE constraint".to_owned())
}
pub async fn bulk_insert<T>(&self, table_name: &str, body: Vec<T>) -> Result<(), String>
where
T: serde::Serialize,
{
let Ok(body) = serde_json::to_value(body) else {
return Err("Failed to serialize body".to_owned());
};
let endpoint: String = self.endpoint(table_name);
#[cfg(feature = "nightly")]
use crate::nightly::print_nightly_warning;
#[cfg(feature = "nightly")]
print_nightly_warning();
let response: Response = match self
.client
.post(&endpoint)
.header(HeadersTypes::ApiKey, &self.api_key)
.header(
HeadersTypes::Authorization,
format!("Bearer {}", &self.api_key),
)
.header(HeadersTypes::ContentType, "application/json")
.header(HeadersTypes::ClientInfo, &crate::client_info())
.header(HeadersTypes::ContentProfile.as_str(), self.schema.as_str())
.body(body.to_string())
.send()
.await
{
Ok(response) => response,
Err(e) => return Err(e.to_string()),
};
if response.status().is_success() {
Ok(())
} else if response.status().as_u16() == 409 {
println!("\x1b[31mError 409: Duplicate entry. The value you're trying to insert may already exist in a column with a UNIQUE constraint.\x1b[0m");
Err("Error 409: Duplicate entry. The value you're trying to insert may already exist in a column with a UNIQUE constraint.".to_owned())
} else {
println!("\x1b[31mError: {:?}\x1b[0m", response);
Err(response.status().to_string())
}
}
}