use crate::{
column::{Column, ColumnType},
sanitizing::SanitizedIdentifier,
};
pub const BLOB_BUF_SIZE: usize = 4096;
pub fn drop_table_if_exists(table_name: &SanitizedIdentifier) -> String {
format!("DROP TABLE IF EXISTS {table_name};")
}
pub fn create_table_if_not_exists(
table_name: &SanitizedIdentifier,
columns: &[&SanitizedIdentifier],
) -> String {
let column_part = columns
.iter()
.map(|v| v.as_str())
.collect::<Vec<_>>()
.join(", ");
format!("CREATE TABLE IF NOT EXISTS {table_name} ({column_part})")
}
pub const fn select_pragram_table_info() -> &'static str {
"SELECT name FROM pragma_table_info(?)"
}
pub fn alter_table_add_column(
table_name: &SanitizedIdentifier,
column: &SanitizedIdentifier,
) -> String {
format!("ALTER TABLE {table_name} ADD COLUMN {column}")
}
pub fn insert_row(table_name: &SanitizedIdentifier, columns: &[Column]) -> String {
let insert_values = columns.iter().map(|_| "?".to_string()).collect::<Vec<_>>();
let column_names = columns
.iter()
.map(|v| v.sanitized_name())
.collect::<Vec<_>>();
insert_statement(table_name, &column_names, &insert_values)
}
pub fn insert_blob(
table_name: &SanitizedIdentifier,
columns: &[Column],
blob_size: usize,
) -> String {
let insert_values = columns
.iter()
.map(|v| {
if v.column_type() == ColumnType::Blob {
group_concat_blob(blob_size)
} else {
"?".to_string()
}
})
.collect::<Vec<_>>();
let column_names = columns
.iter()
.map(|v| v.sanitized_name())
.collect::<Vec<_>>();
insert_statement(table_name, &column_names, &insert_values)
}
fn insert_statement(
table_name: &SanitizedIdentifier,
column_names: &[&SanitizedIdentifier],
insert_values: &[String],
) -> String {
let insert_values = insert_values.join(", ");
let column_part = column_names
.iter()
.map(|v| v.as_str())
.collect::<Vec<_>>()
.join(", ");
format!("INSERT INTO {table_name} ({column_part}) VALUES ({insert_values});")
}
pub fn group_concat_blob(blob_size: usize) -> String {
if blob_size <= BLOB_BUF_SIZE {
format!("SUBSTRING((SELECT CAST(data AS BLOB) FROM temp.blob_insert), 1, {blob_size})")
} else {
format!(
"SUBSTRING((SELECT CAST(group_concat(data, '') AS BLOB) FROM temp.blob_insert ORDER BY rowid), 1, {blob_size})"
)
}
}
pub const fn create_temporary_blob_table() -> &'static str {
"CREATE TEMPORARY TABLE blob_insert(data);"
}
pub fn insert_zero_blob(buf_size: usize) -> String {
format!("INSERT INTO temp.blob_insert(data) VALUES(ZEROBLOB({buf_size}));")
}