relay-knowledge 1.1.17

Graph-database-based knowledge graph project.
Documentation
use rusqlite::Connection;

use crate::{
    domain::{CodeQueryKind, CodeRepositoryStatus, CodeRetrievalHit, CodeRetrievalRequest},
    storage::StorageError,
};

use super::super::{
    filter_dedupe_sort_truncate, has_query_field_hit_filters, query_field_filtered_hits_for_gate,
};
use super::{
    ambiguous_callees::search_ambiguous_callee_implementation_hits,
    hit_projection::call_rows_to_hits,
    identity_query::{
        call_identity_hits_can_answer_without_fts, call_identity_leaf_or_selector_is_specific,
        call_identity_query,
    },
    indirect::search_indirect_call_identity_rows,
    row_store::{search_call_fts_rows, search_call_identity_rows},
};

pub(in super::super) fn search_calls(
    connection: &Connection,
    status: &CodeRepositoryStatus,
    request: &CodeRetrievalRequest,
) -> Result<Vec<CodeRetrievalHit>, StorageError> {
    let identity = call_identity_query(request);
    let mut identity_hits = Vec::new();
    if let Some(identity) = &identity {
        let identity_rows = search_call_identity_rows(connection, status, request, identity)?;
        let saturated = identity_rows.saturated;
        let rows = identity_rows
            .rows
            .into_iter()
            .filter(|row| identity.matches_row(row))
            .collect::<Vec<_>>();
        let direct_hit_count = rows.len();
        let implementation_hits =
            search_ambiguous_callee_implementation_hits(connection, status, request, &rows)?;
        identity_hits = call_rows_to_hits(status, request, rows);
        identity_hits.extend(implementation_hits);
        let mut saturated = saturated;
        if request.code_query_kind == CodeQueryKind::Callers
            && !saturated
            && (direct_hit_count == 0
                || call_identity_leaf_or_selector_is_specific(request, identity))
        {
            let indirect_rows =
                search_indirect_call_identity_rows(connection, status, request, identity)?;
            saturated = saturated || indirect_rows.saturated;
            identity_hits.extend(call_rows_to_hits(status, request, indirect_rows.rows));
        }
        let filtered_identity_hits = has_query_field_hit_filters(request)
            .then(|| query_field_filtered_hits_for_gate(&identity_hits, request));
        let identity_gate_hit_count = filtered_identity_hits
            .as_ref()
            .map_or(identity_hits.len(), Vec::len);
        if call_identity_hits_can_answer_without_fts(
            request,
            identity,
            identity_gate_hit_count,
            saturated,
        ) {
            if let Some(mut hits) = filtered_identity_hits {
                hits.truncate(request.limit);
                return Ok(hits);
            }
            filter_dedupe_sort_truncate(&mut identity_hits, request);
            return Ok(identity_hits);
        }
    }

    let mut hits = call_rows_to_hits(
        status,
        request,
        search_call_fts_rows(connection, status, request)?,
    );
    hits.extend(identity_hits);

    Ok(hits)
}