use rustc_hash::{FxHashMap, FxHashSet};
use std::sync::{Arc, RwLock};
use crate::expression::logical::OrExpr;
use crate::expression::Expression;
use crate::index::{
BTreeIndex, BitmapIndex, HashIndex, HnswIndex, MultiColumnIndex, PartialIndex,
PartialIndexPredicate,
};
use crate::mvcc::{get_fast_timestamp, TransactionVersionStore, VersionStore};
use crate::traits::table::DeferredSum;
use crate::traits::MVCCScanner;
use crate::traits::MemoryResult;
use crate::traits::{Index, QueryResult, ScanPlan, Scanner, Table};
use radixdb_core::{CompactArc, I64Set};
use radixdb_core::{
DataType, Error, IndexType, Result, Row, RowIdVec, RowVec, Schema, SchemaColumn, Value,
};
#[derive(Clone)]
struct CompositeRangeBounds {
min: Option<(Value, bool)>,
max: Option<(Value, bool)>,
}
#[derive(Clone)]
struct CompositeIndexLookupPlan {
index: Arc<dyn Index>,
equality_values: Vec<Value>,
range: Option<CompositeRangeBounds>,
columns: Vec<String>,
conditions: Vec<String>,
covered_columns: FxHashSet<String>,
}
impl CompositeIndexLookupPlan {
fn lookup_row_ids(&self) -> Result<Option<RowIdVec>> {
if let Some(range) = &self.range {
let mut min_key = self.equality_values.clone();
let mut max_key = self.equality_values.clone();
let min_inclusive = if let Some((value, inclusive)) = &range.min {
min_key.push(value.clone());
*inclusive
} else {
true
};
let max_inclusive = if let Some((value, inclusive)) = &range.max {
max_key.push(value.clone());
*inclusive
} else {
true
};
let entries =
self.index
.find_range(&min_key, &max_key, min_inclusive, max_inclusive)?;
let mut ids = RowIdVec::with_capacity(entries.len());
ids.extend(entries.into_iter().map(|entry| entry.row_id));
Ok(Some(ids))
} else {
Ok(Some(self.index.get_row_ids_equal(&self.equality_values)?))
}
}
fn lookup_ordered_limited(
&self,
ascending: bool,
limit: usize,
) -> Option<Vec<radixdb_core::IndexEntry>> {
let range = self.range.as_ref()?;
let mut min_key = self.equality_values.clone();
let mut max_key = self.equality_values.clone();
let min_inclusive = if let Some((value, inclusive)) = &range.min {
min_key.push(value.clone());
*inclusive
} else {
true
};
let max_inclusive = if let Some((value, inclusive)) = &range.max {
max_key.push(value.clone());
*inclusive
} else {
true
};
self.index
.find_range_ordered_limited(
&min_key,
&max_key,
min_inclusive,
max_inclusive,
ascending,
limit,
)
.ok()
}
}
pub(crate) struct MVCCTable {
txn_id: i64,
version_store: Arc<VersionStore>,
txn_versions: Arc<RwLock<TransactionVersionStore>>,
cached_schema: CompactArc<Schema>,
allow_direct_commit: bool,
}
mod inherent;
mod table_impl;
fn operator_to_string(op: radixdb_core::Operator) -> &'static str {
use radixdb_core::Operator;
match op {
Operator::Eq => "=",
Operator::Ne => "!=",
Operator::Lt => "<",
Operator::Lte => "<=",
Operator::Gt => ">",
Operator::Gte => ">=",
Operator::Like => "LIKE",
Operator::In => "IN",
Operator::NotIn => "NOT IN",
Operator::IsNull => "IS NULL",
Operator::IsNotNull => "IS NOT NULL",
}
}
#[cfg(test)]
mod tests;