unobtanium 3.0.0

Opinioated Web search engine library with crawler and viewer companion.
Documentation
use log::{trace,error};
use rusqlite::params;

use crate::content::LinkLocality;
use crate::database::error::SmuggleDatabaseErrorExtension;
use crate::database::id::EntityGenerationId;
use crate::database::DatabaseError;
use crate::database::Page;
use crate::database::sqlite_helper::*;
use crate::database::summary::structs::SummaryDatabase;
use crate::database::summary::structs::SummaryDatabaseTransaction;
use crate::summary::LinkSummary;
use crate::summary::LinkType;
use crate::summary::WithEntityGenerationUuid;

impl SummaryDatabase {
	pub fn get_link_summaries(
		&self,
		entity_generation_id: EntityGenerationId,
		page: &Page,
	) -> Result<Vec<LinkSummary>, DatabaseError> {
		trace!("summary_db.get_link_summaries()");
		let mut get_link_summaries_statement = self.connection().prepare("
			SELECT
				link_to_url,
				rel_nofollow,
				rel_me,
				rel_tag,
				in_header,
				in_footer,
				in_aside,
				in_nav,
				in_form,
				in_main,
				in_article,
				in_section,
				in_table,
				in_figure,
				in_address,
				in_code,
				in_headline,
				in_list,
				in_paragraph,
				contains_headline,
				destination_type,
				link_locality,
				html_tag_name,
				link_to_fragment,
				text
			FROM link_summary
			WHERE entity_generation_id = ?
			LIMIT ?
			OFFSET ?
		")?;
		return get_link_summaries_statement.query_map(
			(entity_generation_id, page.limit(), page.offset()),
			|row| {
				let url = url_with_fragment_from_row(self.base(), row, 0, 23)
					.smuggle_through_rusqlite()?;
				Ok(LinkSummary {
					url: url,
					rel_nofollow: row.get(1)?,
					rel_me: row.get(2)?,
					rel_tag: row.get(3)?,
					location_signature:
						location_signature_from_row_and_15_columns(row, 4)?,
					contains_headline: row.get(19)?,
					link_destination_type: row.get::<usize,Option<u16>>(20)?
						.map(LinkType::from_number),
					link_locality: LinkLocality::from_u8_or_outlink(row.get(21)?),
					html_tag_name: row.get(22)?,
					// 23: link fragment
					text: row.get(24)?,
				})
			}
		)?.map(|r| r.map_err(Into::into)).collect();
	}
}

impl SummaryDatabaseTransaction<'_> {

	pub fn store_link_summaries_bulk(
		&mut self,
		link_summaries: Vec<WithEntityGenerationUuid<Vec<LinkSummary>>>
	) -> Result<(), DatabaseError> {

		self.base_transaction.assert_writable("store_link_summaries_bulk")?;
		
		trace!("summary_db_transaction.store_link_summaries_bulk()");
		let mut statement = self.connection().prepare_cached(
			"INSERT INTO link_summary (
				entity_generation_id,
				link_to_url,
				rel_nofollow,
				rel_me,
				rel_tag,
				in_header,
				in_footer,
				in_aside,
				in_nav,
				in_form,
				in_main,
				in_article,
				in_section,
				in_table,
				in_figure,
				in_address,
				in_code,
				in_headline,
				in_list,
				in_paragraph,
				contains_headline,
				destination_type,
				link_locality,
				html_tag_name,
				link_to_fragment,
				text
			) VALUES (
				?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?
			)"
		)?;
		for summary_list in link_summaries {
			let entity_generation_id = self.get_entity_generation_id(summary_list.entity_generation_uuid)
				.map_err(|e| { error!("Unable to find entity generation: {} ({e})", summary_list.entity_generation_uuid); e })?;
			for link_summary in summary_list.data {
				statement.execute(params![
						entity_generation_id,
						self.base_transaction.get_url_id(&link_summary.url.clone().into(), true)?,
						link_summary.rel_nofollow,
						link_summary.rel_me,
						link_summary.rel_tag,
						link_summary.location_signature.in_header,
						link_summary.location_signature.in_footer,
						link_summary.location_signature.in_aside,
						link_summary.location_signature.in_nav,
						link_summary.location_signature.in_form,
						link_summary.location_signature.in_main,
						link_summary.location_signature.in_article,
						link_summary.location_signature.in_section,
						link_summary.location_signature.in_table,
						link_summary.location_signature.in_figure,
						link_summary.location_signature.in_address,
						link_summary.location_signature.in_code,
						link_summary.location_signature.in_headline,
						link_summary.location_signature.in_list,
						link_summary.location_signature.in_paragraph,
						link_summary.contains_headline,
						link_summary.link_destination_type.map(|t| t.to_number()),
						link_summary.link_locality as u8,
						link_summary.html_tag_name,
						link_summary.url.fragment().map(|f| f.to_string()),
						link_summary.text
					]
				)?;
			}
		}
		return Ok(());
	}

}