radixdb-executor 1.1.0

SQL binding, planning, and execution engine for RadixDB
Documentation
use std::collections::BTreeMap;
use std::sync::{Arc, Mutex};

use radixdb_catalog::ObjectId;

use super::trigger::PublishedTrigger;
use super::PublishedRoutine;

const MAX_COMPILED_ROUTINES: usize = 1024;

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub(super) struct RoutineCacheKey {
    pub database_id: [u8; 16],
    pub catalog_id: [u8; 16],
    pub catalog_generation: u64,
    pub object_id: ObjectId,
    pub definition_revision: u64,
    pub source_digest: [u8; 32],
    pub dependency_versions: Vec<(ObjectId, u64)>,
    pub compiler_abi: u32,
    pub runtime_abi: u32,
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub(super) struct TriggerCacheKey {
    pub database_id: [u8; 16],
    pub catalog_id: [u8; 16],
    pub catalog_generation: u64,
    pub trigger_id: ObjectId,
    pub trigger_revision: u64,
    pub function_id: ObjectId,
    pub function_revision: u64,
    pub source_digest: [u8; 32],
    pub table_id: ObjectId,
    pub table_revision: u64,
    pub event: u16,
    pub timing: u8,
    pub level: u8,
    pub dependency_versions: Vec<(ObjectId, u64)>,
    pub compiler_abi: u32,
    pub runtime_abi: u32,
}

#[derive(Default)]
pub(crate) struct ProceduralProgramCache {
    entries: Mutex<BTreeMap<RoutineCacheKey, Arc<PublishedRoutine>>>,
    trigger_entries: Mutex<BTreeMap<TriggerCacheKey, Arc<PublishedTrigger>>>,
}

impl ProceduralProgramCache {
    pub(super) fn get(&self, key: &RoutineCacheKey) -> Option<Arc<PublishedRoutine>> {
        self.entries.lock().unwrap().get(key).cloned()
    }

    pub(super) fn insert(
        &self,
        key: RoutineCacheKey,
        routine: Arc<PublishedRoutine>,
    ) -> Arc<PublishedRoutine> {
        let mut entries = self.entries.lock().unwrap();
        if entries.len() >= MAX_COMPILED_ROUTINES {
            entries.clear();
        }
        entries.insert(key, Arc::clone(&routine));
        routine
    }

    pub(crate) fn clear(&self) {
        self.entries.lock().unwrap().clear();
        self.trigger_entries.lock().unwrap().clear();
    }

    pub(super) fn get_trigger(&self, key: &TriggerCacheKey) -> Option<Arc<PublishedTrigger>> {
        self.trigger_entries.lock().unwrap().get(key).cloned()
    }

    pub(super) fn insert_trigger(
        &self,
        key: TriggerCacheKey,
        trigger: Arc<PublishedTrigger>,
    ) -> Arc<PublishedTrigger> {
        let mut entries = self.trigger_entries.lock().unwrap();
        if entries.len() >= MAX_COMPILED_ROUTINES {
            entries.clear();
        }
        entries.insert(key, Arc::clone(&trigger));
        trigger
    }

    #[cfg(test)]
    pub(crate) fn len(&self) -> usize {
        self.entries.lock().unwrap().len() + self.trigger_entries.lock().unwrap().len()
    }
}