mirror of
https://github.com/tursodatabase/limbo.git
synced 2025-08-04 18:18:03 +00:00
feat: initial implementation of Statement::bind
This commit is contained in:
parent
b589203fea
commit
08c8c655e9
12 changed files with 241 additions and 6 deletions
111
core/parameters.rs
Normal file
111
core/parameters.rs
Normal file
|
@ -0,0 +1,111 @@
|
|||
use std::num::NonZero;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Parameter {
|
||||
Anonymous(NonZero<usize>),
|
||||
Indexed(NonZero<usize>),
|
||||
Named(String, NonZero<usize>),
|
||||
}
|
||||
|
||||
impl PartialEq for Parameter {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.index() == other.index()
|
||||
}
|
||||
}
|
||||
|
||||
impl Parameter {
|
||||
pub fn index(&self) -> NonZero<usize> {
|
||||
match self {
|
||||
Parameter::Anonymous(index) => *index,
|
||||
Parameter::Indexed(index) => *index,
|
||||
Parameter::Named(_, index) => *index,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Parameters {
|
||||
index: NonZero<usize>,
|
||||
pub list: Vec<Parameter>,
|
||||
}
|
||||
|
||||
impl Parameters {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
index: 1.try_into().unwrap(),
|
||||
list: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn count(&self) -> usize {
|
||||
let mut params = self.list.clone();
|
||||
params.dedup();
|
||||
params.len()
|
||||
}
|
||||
|
||||
pub fn name(&self, index: NonZero<usize>) -> Option<String> {
|
||||
self.list.iter().find_map(|p| match p {
|
||||
Parameter::Anonymous(i) if *i == index => Some("?".to_string()),
|
||||
Parameter::Indexed(i) if *i == index => Some(format!("?{i}")),
|
||||
Parameter::Named(name, i) if *i == index => Some(name.to_owned()),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn index(&self, name: impl AsRef<str>) -> Option<NonZero<usize>> {
|
||||
self.list
|
||||
.iter()
|
||||
.find_map(|p| match p {
|
||||
Parameter::Named(n, index) if n == name.as_ref() => Some(index),
|
||||
_ => None,
|
||||
})
|
||||
.copied()
|
||||
}
|
||||
|
||||
pub fn next_index(&mut self) -> NonZero<usize> {
|
||||
let index = self.index;
|
||||
self.index = self.index.checked_add(1).unwrap();
|
||||
index
|
||||
}
|
||||
|
||||
pub fn push(&mut self, name: impl AsRef<str>) -> NonZero<usize> {
|
||||
match name.as_ref() {
|
||||
"" => {
|
||||
let index = self.next_index();
|
||||
self.list.push(Parameter::Anonymous(index));
|
||||
log::trace!("anonymous parameter at {index}");
|
||||
index
|
||||
}
|
||||
name if name.starts_with(&['$', ':', '@', '#']) => {
|
||||
match self
|
||||
.list
|
||||
.iter()
|
||||
.find(|p| matches!(p, Parameter::Named(n, _) if name == n))
|
||||
{
|
||||
Some(t) => {
|
||||
let index = t.index();
|
||||
self.list.push(t.clone());
|
||||
log::trace!("named parameter at {index} as {name}");
|
||||
index
|
||||
}
|
||||
None => {
|
||||
let index = self.next_index();
|
||||
self.list.push(Parameter::Named(name.to_owned(), index));
|
||||
log::trace!("named parameter at {index} as {name}");
|
||||
index
|
||||
}
|
||||
}
|
||||
}
|
||||
index => {
|
||||
// SAFETY: Garanteed from parser that the index is bigger that 0.
|
||||
let index: NonZero<usize> = index.parse().unwrap();
|
||||
if index > self.index {
|
||||
self.index = index.checked_add(1).unwrap();
|
||||
}
|
||||
self.list.push(Parameter::Indexed(index));
|
||||
log::trace!("indexed parameter at {index}");
|
||||
index
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue