use selene_core::Value;
use crate::procedure_registry::{ProcedureError, ProcedureHandle};
use crate::{
GraphContext, MaintenanceContext, MutationContext, ProcedureMetadata, ProcedureMutability,
ProcedureOutputColumn, ProcedureOutputSchema, ProcedureParameter, ProcedureResult,
ProcedureSignature, ProcedureTier,
};
use super::{
compaction, create_index, create_text_index, create_vector_index, drop_index, drop_text_index,
drop_vector_index, feature_status, health, json_candidate_nodes, json_contains_nodes,
json_path_contains_nodes, json_path_exists_nodes, json_path_value_nodes,
rebuild_vector_indexes, reciprocal_rank_fusion, text_index_stats, text_search,
vector_candidate_states, vector_index_stats, vector_score_candidate_state,
vector_score_candidate_state_expanded, vector_score_candidate_state_expanded_batch,
vector_score_candidate_state_nodes, vector_score_expanded_candidates,
vector_score_expanded_candidates_batch, vector_score_neighbors, vector_score_neighbors_batch,
vector_score_nodes, vector_score_nodes_batch, vector_search, vector_search_ann,
vector_search_ann_batch, vector_search_batch, vector_search_candidate_state_expanded_ann,
vector_search_expanded_candidates_ann, vector_search_expanded_candidates_ann_batch, verify,
};
mod specs;
pub(in crate::runtime) use specs::BUILTIN_SPECS;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(in crate::runtime) enum BuiltinKind {
Health,
FeatureStatus,
Verify,
CompactionStats,
VectorSearchNodes,
VectorSearchNodesBatch,
VectorScoreNodes,
VectorScoreNodesBatch,
VectorScoreNeighbors,
VectorScoreNeighborsBatch,
VectorScoreCandidateState,
VectorScoreCandidateStateNodes,
VectorScoreCandidateStateExpanded,
VectorScoreCandidateStateExpandedBatch,
VectorCandidateStates,
VectorScoreExpandedCandidates,
VectorScoreExpandedCandidatesBatch,
VectorSearchNodesAnn,
VectorSearchNodesAnnBatch,
VectorSearchExpandedCandidatesAnn,
VectorSearchCandidateStateExpandedAnn,
VectorSearchExpandedCandidatesAnnBatch,
VectorIndexStats,
TextIndexStats,
JsonContainsNodes,
JsonPathExistsNodes,
JsonPathContainsNodes,
JsonPathValueNodes,
JsonContainsCandidateNodes,
JsonPathExistsCandidateNodes,
JsonPathContainsCandidateNodes,
JsonPathValueCandidateNodes,
RebuildVectorIndexes,
RebuildRecommendedVectorIndexes,
Compact,
CreateIndex,
DropIndex,
CreateVectorIndex,
DropVectorIndex,
CreateTextIndex,
DropTextIndex,
TextSearchNodes,
TextScoreNodes,
TextScoreNodesBatch,
TextScoreCandidateState,
TextScoreCandidateStateNodes,
TextScoreCandidateStateExpandedBatch,
ReciprocalRankFusion,
}
impl BuiltinKind {
pub(in crate::runtime) fn metadata(
self,
handle: ProcedureHandle,
description: &'static str,
since_version: &'static str,
) -> ProcedureMetadata {
let signature = ProcedureSignature::new(self.signature()).with_since_version(since_version);
ProcedureMetadata::new(
handle,
signature,
ProcedureOutputSchema {
columns: self.output_columns(),
},
self.tier(),
self.mutability(),
)
.with_description(description)
}
pub(in crate::runtime) const fn tier(self) -> ProcedureTier {
match self {
Self::Health
| Self::FeatureStatus
| Self::Verify
| Self::CompactionStats
| Self::VectorSearchNodes
| Self::VectorSearchNodesBatch
| Self::VectorScoreNodes
| Self::VectorScoreNodesBatch
| Self::VectorScoreNeighbors
| Self::VectorScoreNeighborsBatch
| Self::VectorScoreCandidateState
| Self::VectorScoreCandidateStateNodes
| Self::VectorScoreCandidateStateExpanded
| Self::VectorScoreCandidateStateExpandedBatch
| Self::VectorCandidateStates
| Self::VectorScoreExpandedCandidates
| Self::VectorScoreExpandedCandidatesBatch
| Self::VectorSearchNodesAnn
| Self::VectorSearchNodesAnnBatch
| Self::VectorSearchExpandedCandidatesAnn
| Self::VectorSearchCandidateStateExpandedAnn
| Self::VectorSearchExpandedCandidatesAnnBatch
| Self::VectorIndexStats
| Self::TextIndexStats
| Self::JsonContainsNodes
| Self::JsonPathExistsNodes
| Self::JsonPathContainsNodes
| Self::JsonPathValueNodes
| Self::JsonContainsCandidateNodes
| Self::JsonPathExistsCandidateNodes
| Self::JsonPathContainsCandidateNodes
| Self::JsonPathValueCandidateNodes
| Self::TextSearchNodes
| Self::TextScoreNodes
| Self::TextScoreNodesBatch
| Self::TextScoreCandidateState
| Self::TextScoreCandidateStateNodes
| Self::TextScoreCandidateStateExpandedBatch
| Self::ReciprocalRankFusion => ProcedureTier::Graph,
Self::RebuildVectorIndexes | Self::RebuildRecommendedVectorIndexes | Self::Compact => {
ProcedureTier::Maintenance
}
Self::CreateIndex
| Self::DropIndex
| Self::CreateVectorIndex
| Self::DropVectorIndex
| Self::CreateTextIndex
| Self::DropTextIndex => ProcedureTier::Mutation,
}
}
pub(in crate::runtime) const fn mutability(self) -> ProcedureMutability {
match self {
Self::Health
| Self::FeatureStatus
| Self::Verify
| Self::CompactionStats
| Self::VectorSearchNodes
| Self::VectorSearchNodesBatch
| Self::VectorScoreNodes
| Self::VectorScoreNodesBatch
| Self::VectorScoreNeighbors
| Self::VectorScoreNeighborsBatch
| Self::VectorScoreCandidateState
| Self::VectorScoreCandidateStateNodes
| Self::VectorScoreCandidateStateExpanded
| Self::VectorScoreCandidateStateExpandedBatch
| Self::VectorCandidateStates
| Self::VectorScoreExpandedCandidates
| Self::VectorScoreExpandedCandidatesBatch
| Self::VectorSearchNodesAnn
| Self::VectorSearchNodesAnnBatch
| Self::VectorSearchExpandedCandidatesAnn
| Self::VectorSearchCandidateStateExpandedAnn
| Self::VectorSearchExpandedCandidatesAnnBatch
| Self::VectorIndexStats
| Self::TextIndexStats
| Self::JsonContainsNodes
| Self::JsonPathExistsNodes
| Self::JsonPathContainsNodes
| Self::JsonPathValueNodes
| Self::JsonContainsCandidateNodes
| Self::JsonPathExistsCandidateNodes
| Self::JsonPathContainsCandidateNodes
| Self::JsonPathValueCandidateNodes
| Self::TextSearchNodes
| Self::TextScoreNodes
| Self::TextScoreNodesBatch
| Self::TextScoreCandidateState
| Self::TextScoreCandidateStateNodes
| Self::TextScoreCandidateStateExpandedBatch
| Self::ReciprocalRankFusion => ProcedureMutability::Read,
Self::RebuildVectorIndexes | Self::RebuildRecommendedVectorIndexes | Self::Compact => {
ProcedureMutability::MaintenanceWrite
}
Self::CreateIndex
| Self::DropIndex
| Self::CreateVectorIndex
| Self::DropVectorIndex
| Self::CreateTextIndex
| Self::DropTextIndex => ProcedureMutability::SchemaWrite,
}
}
fn signature(self) -> Vec<ProcedureParameter> {
match self {
Self::Health => health::signature(),
Self::FeatureStatus => feature_status::signature(),
Self::Verify => verify::signature(),
Self::CompactionStats | Self::Compact => compaction::signature(),
Self::VectorSearchNodes => vector_search::signature(),
Self::VectorSearchNodesBatch => vector_search_batch::signature(),
Self::VectorScoreNodes => vector_score_nodes::signature(),
Self::VectorScoreNodesBatch => vector_score_nodes_batch::signature(),
Self::VectorScoreNeighbors => vector_score_neighbors::signature(),
Self::VectorScoreNeighborsBatch => vector_score_neighbors_batch::signature(),
Self::VectorScoreCandidateState => vector_score_candidate_state::signature(),
Self::VectorScoreCandidateStateNodes => vector_score_candidate_state_nodes::signature(),
Self::VectorScoreCandidateStateExpanded => {
vector_score_candidate_state_expanded::signature()
}
Self::VectorScoreCandidateStateExpandedBatch => {
vector_score_candidate_state_expanded_batch::signature()
}
Self::VectorCandidateStates => vector_candidate_states::signature(),
Self::VectorScoreExpandedCandidates => vector_score_expanded_candidates::signature(),
Self::VectorScoreExpandedCandidatesBatch => {
vector_score_expanded_candidates_batch::signature()
}
Self::VectorSearchNodesAnn => vector_search_ann::signature(),
Self::VectorSearchNodesAnnBatch => vector_search_ann_batch::signature(),
Self::VectorSearchExpandedCandidatesAnn => {
vector_search_expanded_candidates_ann::signature()
}
Self::VectorSearchCandidateStateExpandedAnn => {
vector_search_candidate_state_expanded_ann::signature()
}
Self::VectorSearchExpandedCandidatesAnnBatch => {
vector_search_expanded_candidates_ann_batch::signature()
}
Self::VectorIndexStats => vector_index_stats::signature(),
Self::TextIndexStats => text_index_stats::signature(),
Self::JsonContainsNodes => json_contains_nodes::signature(),
Self::JsonPathExistsNodes => json_path_exists_nodes::signature(),
Self::JsonPathContainsNodes => json_path_contains_nodes::signature(),
Self::JsonPathValueNodes => json_path_value_nodes::signature(),
Self::JsonContainsCandidateNodes => json_candidate_nodes::contains_signature(),
Self::JsonPathExistsCandidateNodes => json_candidate_nodes::path_exists_signature(),
Self::JsonPathContainsCandidateNodes => json_candidate_nodes::path_contains_signature(),
Self::JsonPathValueCandidateNodes => json_candidate_nodes::path_value_signature(),
Self::RebuildVectorIndexes => rebuild_vector_indexes::signature(),
Self::RebuildRecommendedVectorIndexes => {
rebuild_vector_indexes::recommended_signature()
}
Self::CreateIndex => create_index::signature(),
Self::DropIndex => drop_index::signature(),
Self::CreateVectorIndex => create_vector_index::signature(),
Self::DropVectorIndex => drop_vector_index::signature(),
Self::CreateTextIndex => create_text_index::signature(),
Self::DropTextIndex => drop_text_index::signature(),
Self::TextSearchNodes => text_search::signature(),
Self::TextScoreNodes => text_search::score_signature(),
Self::TextScoreNodesBatch => text_search::score_batch_signature(),
Self::TextScoreCandidateState => text_search::score_state_signature(),
Self::TextScoreCandidateStateNodes => text_search::score_state_nodes_signature(),
Self::TextScoreCandidateStateExpandedBatch => {
text_search::score_state_expanded_batch_signature()
}
Self::ReciprocalRankFusion => reciprocal_rank_fusion::signature(),
}
}
fn output_columns(self) -> Vec<ProcedureOutputColumn> {
match self {
Self::Health => health::output_columns(),
Self::FeatureStatus => feature_status::output_columns(),
Self::Verify => verify::output_columns(),
Self::CompactionStats => compaction::output_columns(),
Self::VectorSearchNodes => vector_search::output_columns(),
Self::VectorSearchNodesBatch => vector_search_batch::output_columns(),
Self::VectorScoreNodes => vector_score_nodes::output_columns(),
Self::VectorScoreNodesBatch => vector_score_nodes_batch::output_columns(),
Self::VectorScoreNeighbors => vector_score_neighbors::output_columns(),
Self::VectorScoreNeighborsBatch => vector_score_neighbors_batch::output_columns(),
Self::VectorScoreCandidateState => vector_score_candidate_state::output_columns(),
Self::VectorScoreCandidateStateNodes => {
vector_score_candidate_state_nodes::output_columns()
}
Self::VectorScoreCandidateStateExpanded => {
vector_score_candidate_state_expanded::output_columns()
}
Self::VectorScoreCandidateStateExpandedBatch => {
vector_score_candidate_state_expanded_batch::output_columns()
}
Self::VectorCandidateStates => vector_candidate_states::output_columns(),
Self::VectorScoreExpandedCandidates => {
vector_score_expanded_candidates::output_columns()
}
Self::VectorScoreExpandedCandidatesBatch => {
vector_score_expanded_candidates_batch::output_columns()
}
Self::VectorSearchNodesAnn => vector_search_ann::output_columns(),
Self::VectorSearchNodesAnnBatch => vector_search_ann_batch::output_columns(),
Self::VectorSearchExpandedCandidatesAnn => {
vector_search_expanded_candidates_ann::output_columns()
}
Self::VectorSearchCandidateStateExpandedAnn => {
vector_search_candidate_state_expanded_ann::output_columns()
}
Self::VectorSearchExpandedCandidatesAnnBatch => {
vector_search_expanded_candidates_ann_batch::output_columns()
}
Self::VectorIndexStats => vector_index_stats::output_columns(),
Self::TextIndexStats => text_index_stats::output_columns(),
Self::JsonContainsNodes => json_contains_nodes::output_columns(),
Self::JsonPathExistsNodes => json_path_exists_nodes::output_columns(),
Self::JsonPathContainsNodes => json_path_contains_nodes::output_columns(),
Self::JsonPathValueNodes => json_path_value_nodes::output_columns(),
Self::JsonContainsCandidateNodes
| Self::JsonPathExistsCandidateNodes
| Self::JsonPathContainsCandidateNodes => json_candidate_nodes::output_columns(),
Self::JsonPathValueCandidateNodes => json_candidate_nodes::value_output_columns(),
Self::RebuildVectorIndexes | Self::RebuildRecommendedVectorIndexes => {
rebuild_vector_indexes::output_columns()
}
Self::Compact => compaction::compact_output_columns(),
Self::CreateIndex => create_index::output_columns(),
Self::DropIndex => drop_index::output_columns(),
Self::CreateVectorIndex => create_vector_index::output_columns(),
Self::DropVectorIndex => drop_vector_index::output_columns(),
Self::CreateTextIndex => create_text_index::output_columns(),
Self::DropTextIndex => drop_text_index::output_columns(),
Self::TextSearchNodes
| Self::TextScoreNodes
| Self::TextScoreCandidateState
| Self::TextScoreCandidateStateNodes => text_search::output_columns(),
Self::TextScoreNodesBatch | Self::TextScoreCandidateStateExpandedBatch => {
text_search::score_batch_output_columns()
}
Self::ReciprocalRankFusion => reciprocal_rank_fusion::output_columns(),
}
}
pub(in crate::runtime) fn execute_graph(
self,
ctx: &GraphContext<'_>,
args: &[Value],
) -> Result<ProcedureResult, ProcedureError> {
match self {
Self::Health => health::execute(ctx, args),
Self::FeatureStatus => feature_status::execute(ctx, args),
Self::Verify => verify::execute(ctx, args),
Self::CompactionStats => compaction::execute_stats(ctx, args),
Self::VectorSearchNodes => vector_search::execute(ctx, args),
Self::VectorSearchNodesBatch => vector_search_batch::execute(ctx, args),
Self::VectorScoreNodes => vector_score_nodes::execute(ctx, args),
Self::VectorScoreNodesBatch => vector_score_nodes_batch::execute(ctx, args),
Self::VectorScoreNeighbors => vector_score_neighbors::execute(ctx, args),
Self::VectorScoreNeighborsBatch => vector_score_neighbors_batch::execute(ctx, args),
Self::VectorScoreCandidateState => vector_score_candidate_state::execute(ctx, args),
Self::VectorScoreCandidateStateNodes => {
vector_score_candidate_state_nodes::execute(ctx, args)
}
Self::VectorScoreCandidateStateExpanded => {
vector_score_candidate_state_expanded::execute(ctx, args)
}
Self::VectorScoreCandidateStateExpandedBatch => {
vector_score_candidate_state_expanded_batch::execute(ctx, args)
}
Self::VectorCandidateStates => vector_candidate_states::execute(ctx, args),
Self::VectorScoreExpandedCandidates => {
vector_score_expanded_candidates::execute(ctx, args)
}
Self::VectorScoreExpandedCandidatesBatch => {
vector_score_expanded_candidates_batch::execute(ctx, args)
}
Self::VectorSearchNodesAnn => vector_search_ann::execute(ctx, args),
Self::VectorSearchNodesAnnBatch => vector_search_ann_batch::execute(ctx, args),
Self::VectorSearchExpandedCandidatesAnn => {
vector_search_expanded_candidates_ann::execute(ctx, args)
}
Self::VectorSearchCandidateStateExpandedAnn => {
vector_search_candidate_state_expanded_ann::execute(ctx, args)
}
Self::VectorSearchExpandedCandidatesAnnBatch => {
vector_search_expanded_candidates_ann_batch::execute(ctx, args)
}
Self::VectorIndexStats => vector_index_stats::execute(ctx, args),
Self::TextIndexStats => text_index_stats::execute(ctx, args),
Self::JsonContainsNodes => json_contains_nodes::execute(ctx, args),
Self::JsonPathExistsNodes => json_path_exists_nodes::execute(ctx, args),
Self::JsonPathContainsNodes => json_path_contains_nodes::execute(ctx, args),
Self::JsonPathValueNodes => json_path_value_nodes::execute(ctx, args),
Self::JsonContainsCandidateNodes => json_candidate_nodes::execute_contains(ctx, args),
Self::JsonPathExistsCandidateNodes => {
json_candidate_nodes::execute_path_exists(ctx, args)
}
Self::JsonPathContainsCandidateNodes => {
json_candidate_nodes::execute_path_contains(ctx, args)
}
Self::JsonPathValueCandidateNodes => {
json_candidate_nodes::execute_path_value(ctx, args)
}
Self::TextSearchNodes => text_search::execute(ctx, args),
Self::TextScoreNodes => text_search::execute_score(ctx, args),
Self::TextScoreNodesBatch => text_search::execute_score_batch(ctx, args),
Self::TextScoreCandidateState => text_search::execute_score_state(ctx, args),
Self::TextScoreCandidateStateNodes => text_search::execute_score_state_nodes(ctx, args),
Self::TextScoreCandidateStateExpandedBatch => {
text_search::execute_score_state_expanded_batch(ctx, args)
}
Self::ReciprocalRankFusion => reciprocal_rank_fusion::execute(ctx, args),
Self::CreateIndex
| Self::DropIndex
| Self::CreateVectorIndex
| Self::DropVectorIndex
| Self::CreateTextIndex
| Self::DropTextIndex => Err(ProcedureError::TierMismatch {
expected: ProcedureTier::Mutation,
actual: ProcedureTier::Graph,
}),
Self::RebuildVectorIndexes | Self::RebuildRecommendedVectorIndexes | Self::Compact => {
Err(ProcedureError::TierMismatch {
expected: ProcedureTier::Maintenance,
actual: ProcedureTier::Graph,
})
}
}
}
pub(in crate::runtime) fn execute_mutation(
self,
ctx: &mut MutationContext<'_, '_>,
args: &[Value],
) -> Result<ProcedureResult, ProcedureError> {
match self {
Self::CreateIndex => create_index::execute(ctx, args),
Self::DropIndex => drop_index::execute(ctx, args),
Self::CreateVectorIndex => create_vector_index::execute(ctx, args),
Self::DropVectorIndex => drop_vector_index::execute(ctx, args),
Self::CreateTextIndex => create_text_index::execute(ctx, args),
Self::DropTextIndex => drop_text_index::execute(ctx, args),
Self::Health
| Self::FeatureStatus
| Self::Verify
| Self::CompactionStats
| Self::VectorSearchNodes
| Self::VectorSearchNodesBatch
| Self::VectorScoreNodes
| Self::VectorScoreNodesBatch
| Self::VectorScoreNeighbors
| Self::VectorScoreNeighborsBatch
| Self::VectorScoreCandidateState
| Self::VectorScoreCandidateStateNodes
| Self::VectorScoreCandidateStateExpanded
| Self::VectorScoreCandidateStateExpandedBatch
| Self::VectorCandidateStates
| Self::VectorScoreExpandedCandidates
| Self::VectorScoreExpandedCandidatesBatch
| Self::VectorSearchNodesAnn
| Self::VectorSearchNodesAnnBatch
| Self::VectorSearchExpandedCandidatesAnn
| Self::VectorSearchCandidateStateExpandedAnn
| Self::VectorSearchExpandedCandidatesAnnBatch
| Self::VectorIndexStats
| Self::TextIndexStats
| Self::JsonContainsNodes
| Self::JsonPathExistsNodes
| Self::JsonPathContainsNodes
| Self::JsonPathValueNodes
| Self::JsonContainsCandidateNodes
| Self::JsonPathExistsCandidateNodes
| Self::JsonPathContainsCandidateNodes
| Self::JsonPathValueCandidateNodes
| Self::TextSearchNodes
| Self::TextScoreNodes
| Self::TextScoreNodesBatch
| Self::TextScoreCandidateState
| Self::TextScoreCandidateStateNodes
| Self::TextScoreCandidateStateExpandedBatch
| Self::ReciprocalRankFusion => Err(ProcedureError::TierMismatch {
expected: ProcedureTier::Graph,
actual: ProcedureTier::Mutation,
}),
Self::RebuildVectorIndexes | Self::RebuildRecommendedVectorIndexes | Self::Compact => {
Err(ProcedureError::TierMismatch {
expected: ProcedureTier::Maintenance,
actual: ProcedureTier::Mutation,
})
}
}
}
pub(in crate::runtime) fn execute_maintenance(
self,
ctx: &MaintenanceContext<'_, '_>,
args: &[Value],
) -> Result<ProcedureResult, ProcedureError> {
match self {
Self::RebuildVectorIndexes => rebuild_vector_indexes::execute(ctx, args),
Self::RebuildRecommendedVectorIndexes => {
rebuild_vector_indexes::execute_recommended(ctx, args)
}
Self::Compact => compaction::execute_compact(ctx, args),
Self::Health
| Self::FeatureStatus
| Self::Verify
| Self::CompactionStats
| Self::VectorSearchNodes
| Self::VectorSearchNodesBatch
| Self::VectorScoreNodes
| Self::VectorScoreNodesBatch
| Self::VectorScoreNeighbors
| Self::VectorScoreNeighborsBatch
| Self::VectorScoreCandidateState
| Self::VectorScoreCandidateStateNodes
| Self::VectorScoreCandidateStateExpanded
| Self::VectorScoreCandidateStateExpandedBatch
| Self::VectorCandidateStates
| Self::VectorScoreExpandedCandidates
| Self::VectorScoreExpandedCandidatesBatch
| Self::VectorSearchNodesAnn
| Self::VectorSearchNodesAnnBatch
| Self::VectorSearchExpandedCandidatesAnn
| Self::VectorSearchCandidateStateExpandedAnn
| Self::VectorSearchExpandedCandidatesAnnBatch
| Self::VectorIndexStats
| Self::TextIndexStats
| Self::JsonContainsNodes
| Self::JsonPathExistsNodes
| Self::JsonPathContainsNodes
| Self::JsonPathValueNodes
| Self::JsonContainsCandidateNodes
| Self::JsonPathExistsCandidateNodes
| Self::JsonPathContainsCandidateNodes
| Self::JsonPathValueCandidateNodes
| Self::TextSearchNodes
| Self::TextScoreNodes
| Self::TextScoreNodesBatch
| Self::TextScoreCandidateState
| Self::TextScoreCandidateStateNodes
| Self::TextScoreCandidateStateExpandedBatch
| Self::ReciprocalRankFusion => Err(ProcedureError::TierMismatch {
expected: ProcedureTier::Graph,
actual: ProcedureTier::Maintenance,
}),
Self::CreateIndex
| Self::DropIndex
| Self::CreateVectorIndex
| Self::DropVectorIndex
| Self::CreateTextIndex
| Self::DropTextIndex => Err(ProcedureError::TierMismatch {
expected: ProcedureTier::Mutation,
actual: ProcedureTier::Maintenance,
}),
}
}
}