bind/js: Refactor presentation modes to use an enum

This commit is contained in:
Diego Reis
2025-06-04 09:20:32 -03:00
parent c7ec4a6270
commit 48056e0941

View File

@@ -202,6 +202,13 @@ impl Database {
}
}
#[derive(Debug, Clone)]
enum PresentationMode {
Raw,
Pluck,
None,
}
#[napi]
#[derive(Clone)]
pub struct Statement {
@@ -216,8 +223,7 @@ pub struct Statement {
pub source: String,
database: Database,
raw: bool,
pluck: bool,
presentation_mode: PresentationMode,
binded: bool,
inner: Rc<RefCell<limbo_core::Statement>>,
}
@@ -229,9 +235,8 @@ impl Statement {
inner: Rc::new(inner),
database,
source,
pluck: false,
presentation_mode: PresentationMode::None,
binded: false,
raw: false,
}
}
@@ -244,43 +249,44 @@ impl Statement {
limbo_core::StepResult::Row => {
let row = stmt.row().unwrap();
if self.raw {
assert!(!self.pluck, "Cannot use raw mode with pluck mode");
match self.presentation_mode {
PresentationMode::Raw => {
let mut raw_obj = env.create_array(row.len() as u32)?;
for (idx, value) in row.get_values().enumerate() {
let js_value = to_js_value(&env, value);
let mut raw_obj = env.create_array(row.len() as u32)?;
for (idx, value) in row.get_values().enumerate() {
let js_value = to_js_value(&env, value);
raw_obj.set(idx as u32, js_value)?;
}
raw_obj.set(idx as u32, js_value)?;
Ok(raw_obj.coerce_to_object()?.into_unknown())
}
PresentationMode::Pluck => {
let mut obj = env.create_object()?;
return Ok(raw_obj.coerce_to_object()?.into_unknown());
let (idx, value) =
row.get_values().enumerate().next().ok_or(napi::Error::new(
napi::Status::GenericFailure,
"Pluck mode requires at least one column in the result",
))?;
let key = stmt.get_column_name(idx);
let js_value = to_js_value(&env, value);
obj.set_named_property(&key, js_value)?;
Ok(obj.into_unknown())
}
PresentationMode::None => {
let mut obj = env.create_object()?;
for (idx, value) in row.get_values().enumerate() {
let key = stmt.get_column_name(idx);
let js_value = to_js_value(&env, value);
obj.set_named_property(&key, js_value)?;
}
Ok(obj.into_unknown())
}
}
let mut obj = env.create_object()?;
if self.pluck {
assert!(!self.raw, "Cannot use pluck mode with raw mode");
let (idx, value) =
row.get_values().enumerate().next().ok_or(napi::Error::new(
napi::Status::GenericFailure,
"Pluck mode requires at least one column in the result",
))?;
let key = stmt.get_column_name(idx);
let js_value = to_js_value(&env, value);
obj.set_named_property(&key, js_value)?;
return Ok(obj.into_unknown());
}
for (idx, value) in row.get_values().enumerate() {
let key = stmt.get_column_name(idx);
let js_value = to_js_value(&env, value);
obj.set_named_property(&key, js_value)?;
}
Ok(obj.into_unknown())
}
limbo_core::StepResult::Done => Ok(env.get_undefined()?.into_unknown()),
limbo_core::StepResult::IO => todo!(),
@@ -305,20 +311,11 @@ impl Statement {
args: Option<Vec<JsUnknown>>,
) -> napi::Result<IteratorStatement> {
self.check_and_bind(args)?;
if self.raw {
assert!(!self.pluck, "Cannot use raw mode with pluck mode");
}
if self.pluck {
assert!(!self.raw, "Cannot use pluck mode with raw mode");
}
Ok(IteratorStatement {
stmt: Rc::clone(&self.inner),
database: self.database.clone(),
env,
pluck: self.pluck,
raw: self.raw,
presentation_mode: self.presentation_mode.clone(),
})
}
@@ -342,42 +339,40 @@ impl Statement {
let row = stmt.row().unwrap();
let mut obj = env.create_object()?;
if self.raw {
assert!(!self.pluck, "Cannot use raw mode with pluck mode");
let mut raw_array = env.create_array(row.len() as u32)?;
for (idx, value) in row.get_values().enumerate() {
let js_value = to_js_value(&env, value)?;
raw_array.set(idx as u32, js_value)?;
match self.presentation_mode {
PresentationMode::Raw => {
let mut raw_array = env.create_array(row.len() as u32)?;
for (idx, value) in row.get_values().enumerate() {
let js_value = to_js_value(&env, value)?;
raw_array.set(idx as u32, js_value)?;
}
results.set_element(index, raw_array.coerce_to_object()?)?;
index += 1;
continue;
}
PresentationMode::Pluck => {
let (idx, value) =
row.get_values().enumerate().next().ok_or(napi::Error::new(
napi::Status::GenericFailure,
"Pluck mode requires at least one column in the result",
))?;
let key = stmt.get_column_name(idx);
let js_value = to_js_value(&env, value)?;
obj.set_named_property(&key, js_value)?;
results.set_element(index, obj)?;
index += 1;
continue;
}
PresentationMode::None => {
for (idx, value) in row.get_values().enumerate() {
let key = stmt.get_column_name(idx);
let js_value = to_js_value(&env, value);
obj.set_named_property(&key, js_value)?;
}
results.set_element(index, obj)?;
index += 1;
}
results.set_element(index, raw_array.coerce_to_object()?)?;
index += 1;
continue;
}
if self.pluck {
assert!(!self.raw, "Cannot use pluck mode with raw mode");
let (idx, value) =
row.get_values().enumerate().next().ok_or(napi::Error::new(
napi::Status::GenericFailure,
"Pluck mode requires at least one column in the result",
))?;
let key = stmt.get_column_name(idx);
let js_value = to_js_value(&env, value)?;
obj.set_named_property(&key, js_value)?;
results.set_element(index, obj)?;
index += 1;
continue;
}
for (idx, value) in row.get_values().enumerate() {
let key = stmt.get_column_name(idx);
let js_value = to_js_value(&env, value);
obj.set_named_property(&key, js_value)?;
}
results.set_element(index, obj)?;
index += 1;
}
limbo_core::StepResult::Done => {
break;
@@ -400,11 +395,10 @@ impl Statement {
#[napi]
pub fn pluck(&mut self, pluck: Option<bool>) {
if let Some(false) = pluck {
self.pluck = false;
self.presentation_mode = PresentationMode::None;
}
self.raw = false;
self.pluck = true;
self.presentation_mode = PresentationMode::Pluck;
}
#[napi]
@@ -415,11 +409,10 @@ impl Statement {
#[napi]
pub fn raw(&mut self, raw: Option<bool>) {
if let Some(false) = raw {
self.raw = false;
self.presentation_mode = PresentationMode::None;
}
self.pluck = false;
self.raw = true;
self.presentation_mode = PresentationMode::Raw;
}
#[napi]
@@ -466,8 +459,7 @@ pub struct IteratorStatement {
stmt: Rc<RefCell<limbo_core::Statement>>,
database: Database,
env: Env,
pluck: bool,
raw: bool,
presentation_mode: PresentationMode,
}
impl Generator for IteratorStatement {
@@ -485,41 +477,38 @@ impl Generator for IteratorStatement {
let row = stmt.row().unwrap();
let mut js_row = self.env.create_object().ok()?;
if self.raw {
assert!(!self.pluck, "Cannot use raw mode with pluck mode");
match self.presentation_mode {
PresentationMode::Raw => {
let mut raw_array = self.env.create_array(row.len() as u32).ok()?;
for (idx, value) in row.get_values().enumerate() {
let js_value = to_js_value(&self.env, value);
raw_array.set(idx as u32, js_value).ok()?;
}
let mut raw_array = self.env.create_array(row.len() as u32).ok()?;
for (idx, value) in row.get_values().enumerate() {
let js_value = to_js_value(&self.env, value);
raw_array.set(idx as u32, js_value).ok()?;
raw_array.coerce_to_object().ok()
}
PresentationMode::Pluck => {
let (idx, value) = row.get_values().enumerate().next()?;
let key = stmt.get_column_name(idx);
let js_value = to_js_value(&self.env, value);
js_row.set_named_property(&key, js_value).ok()?;
Some(js_row)
}
PresentationMode::None => {
for (idx, value) in row.get_values().enumerate() {
let key = stmt.get_column_name(idx);
let js_value = to_js_value(&self.env, value);
js_row.set_named_property(&key, js_value).ok()?;
}
// TODO: fix this unwrap
return Some(raw_array.coerce_to_object().unwrap());
Some(js_row)
}
}
if self.pluck {
assert!(!self.raw, "Cannot use pluck mode with raw mode");
let (idx, value) = row.get_values().enumerate().next()?;
let key = stmt.get_column_name(idx);
let js_value = to_js_value(&self.env, value);
js_row.set_named_property(&key, js_value).ok()?;
return Some(js_row);
}
for (idx, value) in row.get_values().enumerate() {
let key = stmt.get_column_name(idx);
let js_value = to_js_value(&self.env, value);
js_row.set_named_property(&key, js_value).ok()?;
}
Some(js_row)
}
limbo_core::StepResult::Done => None,
limbo_core::StepResult::IO => {
self.database.io.run_once().ok()?;
None // clearly it's incorrect it should return to user
None // clearly it's incorrect, it should return to user
}
limbo_core::StepResult::Interrupt | limbo_core::StepResult::Busy => None,
}