use criterium::CriteriumChain;
use criterium::rusqlite::AssembleRusqliteQuery;
use log::trace;
use mediatype::MediaTypeBuf;
use uuid::Uuid;
use crate::criterium::EntityCriterium;
use crate::database::fields::EntityGenerationField;
use crate::database::fields::FileSummaryField;
use crate::database::id::EntityGenerationId;
use crate::database::id::MimetypeId;
use crate::database::DatabaseError;
use crate::database::EntityComponentTable;
use crate::database::error::SmuggleDatabaseErrorExtension;
use crate::database::Page;
use crate::database::summary::structs::SummaryDatabase;
use crate::database::summary::structs::SummaryDatabaseTransaction;
use crate::summary::DocumentDescription;
use crate::summary::FileSummary;
use crate::summary::TextPile;
use crate::summary::WithEntityGenerationUuid;
impl SummaryDatabase {
pub fn get_file_summary(
&self, entity_generation_id: EntityGenerationId
) -> Result<FileSummary, DatabaseError> {
trace!("summary_db.get_file_summary()");
return self.connection().query_row(
"SELECT
file_size,
mimetype_id,
canonical_url_id
FROM file_summary
WHERE entity_generation_id = ?
",(entity_generation_id,),
|row| {
Ok(file_summary_row_to_summary(self, row, entity_generation_id, true))
}
)?;
}
pub fn get_file_summaries(
&self,
page: &Page,
fetch_text_pile: bool,
criterium_chain: CriteriumChain<EntityCriterium>,
) -> Result<Vec<WithEntityGenerationUuid<FileSummary>>, DatabaseError> {
trace!("summary_db.get_file_summaries()");
let mut query = criterium_chain.assemble_rusqlite_query_for_db(
&EntityComponentTable::FileSummary
).inner_join(
None, EntityGenerationField::EntityGenerationId.into(),
None, FileSummaryField::EntityGenerationId.into()
);
trace!("SQL where: {}", query.sql_where_clause);
trace!("SQL joins: {}", query.joins_to_sql());
let mut get_file_summaries_statement = self.connection().prepare(
format!("
SELECT
file_summary.file_size,
file_summary.mimetype_id,
file_summary.canonical_url_id,
file_summary.entity_generation_id,
entity_generation.entity_generation_uuid
FROM file_summary
{}
WHERE {}
LIMIT ?
OFFSET ?",
query.joins_to_sql(),
query.sql_where_clause).as_str()
)?;
query.where_values.push(page.limit().into());
query.where_values.push(page.offset().into());
return get_file_summaries_statement.query_map(
query.where_values_as_params(),
|row| {
let id: EntityGenerationId = row.get(3)?;
let uuid: Uuid = row.get(4)?;
Ok(WithEntityGenerationUuid {
entity_generation_uuid: uuid,
data: file_summary_row_to_summary(self, row, id, fetch_text_pile)
.smuggle_through_rusqlite()?,
})
}
)?.map(|r| r.map_err(Into::into)).collect();
}
}
impl SummaryDatabaseTransaction<'_> {
pub fn store_file_summary_bulk(
&mut self,
file_summaries: Vec<WithEntityGenerationUuid<FileSummary>>,
) -> Result<(), DatabaseError> {
self.base_transaction.assert_writable("store_file_summary_bulk")?;
trace!("summary_db_transaction.store_file_summary_bulk()");
let mut mimetype_ids = Vec::with_capacity(file_summaries.len());
for file_summary in &file_summaries {
if let Some(ref mimetype) = file_summary.data.mime_type {
mimetype_ids.push(Some(self.base_transaction.get_mimetype_id(mimetype, true)?));
} else {
mimetype_ids.push(None);
}
}
{
let mut store_file_summary_statement = self.connection().prepare_cached(
"INSERT INTO file_summary (
entity_generation_id,
file_size,
mimetype_id
) VALUES (
?,?,?
)"
)?;
for (n,file_summary) in file_summaries.iter().enumerate() {
let mut mimetype_id: Option<MimetypeId> = None;
if let Some(id_opt) = mimetype_ids.get(n) {
mimetype_id = *id_opt;
}
let entity_generation_id = self.get_entity_generation_id(file_summary.entity_generation_uuid)?;
store_file_summary_statement.execute(
(
entity_generation_id,
file_summary.data.size,
mimetype_id,
)
)?;
}
}
for file_summary in file_summaries {
self.store_document_description(
file_summary.entity_generation_uuid,
file_summary.data.description
)?;
if let Some(text_pile) = file_summary.data.text {
self.store_text_pile(
file_summary.entity_generation_uuid,
text_pile
)?;
}
}
return Ok(());
}
}
fn file_summary_row_to_summary(
db: &SummaryDatabase,
row: &rusqlite::Row,
entity_generation_id: EntityGenerationId,
fetch_text_pile: bool,
) -> Result<FileSummary, DatabaseError> {
let mut mimetype: Option<MediaTypeBuf> = None;
if let Some(m_id) = row.get::<usize,Option<MimetypeId>>(1)? {
mimetype = Some(db.base().get_mimetype_by_id(m_id)?);
}
let text: Option<TextPile> = if fetch_text_pile {
db.get_text_pile(entity_generation_id).ok()
} else {
None
};
let description: DocumentDescription = db.get_document_description(entity_generation_id)?;
Ok(FileSummary{
mime_type: mimetype,
size: row.get(0)?,
canonical_url: row.get(2)?,
text: text,
link_stats: None,
description: description,
})
}