use common::fmt::EscapeKwFreeIdent;
use surrealdb_strand::Strand;
use surrealdb_types::{Number as PublicNumber, SqlFormat, ToSql, write_sql};
use crate::Cond;
use crate::scoring::Scoring;
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum Index {
Idx,
Uniq,
Hnsw(HnswParams),
DiskAnn(DiskAnnParams),
FullText(FullTextParams),
Count(Option<Cond>),
}
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Hash)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct FullTextParams {
pub az: Strand,
pub hl: bool,
pub sc: Scoring,
}
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Hash)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct HnswParams {
pub dimension: u16,
pub distance: Distance,
pub vector_type: VectorType,
pub m: u8,
pub m0: u8,
pub ef_construction: u16,
pub extend_candidates: bool,
pub keep_pruned_connections: bool,
pub ml: PublicNumber,
pub use_hashed_vector: bool,
}
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Hash)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct DiskAnnParams {
pub dimension: u16,
pub distance: Distance,
pub vector_type: VectorType,
pub degree: u16,
pub l_build: u16,
pub alpha: PublicNumber,
pub use_hashed_vector: bool,
}
#[derive(Clone, Default, Debug, Eq, PartialEq, PartialOrd, Hash)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum Distance {
Chebyshev,
Cosine,
#[default]
Euclidean,
Hamming,
Jaccard,
Manhattan,
Minkowski(PublicNumber),
Pearson,
CosineNormalized,
InnerProduct,
}
impl ToSql for Distance {
fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
match self {
Self::Chebyshev => f.push_str("CHEBYSHEV"),
Self::Cosine => f.push_str("COSINE"),
Self::CosineNormalized => f.push_str("COSINE_NORMALIZED"),
Self::Euclidean => f.push_str("EUCLIDEAN"),
Self::Hamming => f.push_str("HAMMING"),
Self::InnerProduct => f.push_str("INNER_PRODUCT"),
Self::Jaccard => f.push_str("JACCARD"),
Self::Manhattan => f.push_str("MANHATTAN"),
Self::Minkowski(order) => write_sql!(f, fmt, "MINKOWSKI {}", order),
Self::Pearson => f.push_str("PEARSON"),
}
}
}
#[derive(Clone, Copy, Default, Debug, Eq, PartialEq, PartialOrd, Hash)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum VectorType {
F64,
#[default]
F32,
I64,
I32,
I16,
F16,
I8,
U8,
}
impl ToSql for VectorType {
fn fmt_sql(&self, f: &mut String, _fmt: SqlFormat) {
match self {
Self::F64 => f.push_str("F64"),
Self::F16 => f.push_str("F16"),
Self::F32 => f.push_str("F32"),
Self::I64 => f.push_str("I64"),
Self::I32 => f.push_str("I32"),
Self::I16 => f.push_str("I16"),
Self::I8 => f.push_str("I8"),
Self::U8 => f.push_str("U8"),
}
}
}
impl ToSql for Index {
fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
match self {
Self::Idx => {}
Self::Uniq => f.push_str("UNIQUE"),
Self::Count(c) => {
f.push_str("COUNT");
if let Some(v) = c {
write_sql!(f, fmt, " {}", v)
}
}
Self::FullText(p) => {
write_sql!(f, fmt, "FULLTEXT ANALYZER {} {}", EscapeKwFreeIdent(&p.az), p.sc);
if p.hl {
f.push_str(" HIGHLIGHTS")
}
}
Self::Hnsw(p) => {
write_sql!(
f,
fmt,
"HNSW DIMENSION {} DIST {} TYPE {} EFC {} M {} M0 {} LM {}",
p.dimension,
p.distance,
p.vector_type,
p.ef_construction,
p.m,
p.m0,
p.ml
);
if p.extend_candidates {
f.push_str(" EXTEND_CANDIDATES")
}
if p.keep_pruned_connections {
f.push_str(" KEEP_PRUNED_CONNECTIONS")
}
if p.use_hashed_vector {
f.push_str(" HASHED_VECTOR")
}
}
Self::DiskAnn(p) => {
write_sql!(
f,
fmt,
"DISKANN DIMENSION {} DIST {} TYPE {} DEGREE {} L_BUILD {} ALPHA {}",
p.dimension,
p.distance,
p.vector_type,
p.degree,
p.l_build,
p.alpha
);
if p.use_hashed_vector {
f.push_str(" HASHED_VECTOR")
}
}
}
}
}