use essential_node_db_sql as sql;
use essential_types::{ContentAddress, Key, Value, Word};
use rusqlite::{named_params, Connection, OptionalExtension, Transaction};
use crate::{blob_from_words, words_from_blob, QueryError};
pub fn query_state_inclusive_block(
conn: &Connection,
contract_ca: &ContentAddress,
key: &Key,
block_address: &ContentAddress,
) -> Result<Option<Value>, QueryError> {
let mut stmt = conn.prepare(sql::query::QUERY_STATE_BLOCK_ADDRESS)?;
let value_blob: Option<(Option<Vec<u8>>, Word)> = stmt
.query_row(
named_params! {
":contract_ca": contract_ca.0,
":key": blob_from_words(key),
":block_address": block_address.0,
":solution_set_index": None::<u64>,
},
|row| {
let value = row.get("found_value")?;
let number = row.get("number")?;
Ok((value, number))
},
)
.optional()?;
match value_blob {
None => Ok(None),
Some((Some(value_blob), _)) => Ok(Some(words_from_blob(&value_blob))),
Some((None, block_number)) => {
super::finalized::query_state_inclusive_block(conn, contract_ca, key, block_number)
}
}
}
pub fn query_state_exclusive_block(
tx: &Transaction,
contract_ca: &ContentAddress,
key: &Key,
block_address: &ContentAddress,
) -> Result<Option<Value>, QueryError> {
let Some(parent_addr) = crate::get_parent_block_address(tx, block_address)? else {
return Ok(None);
};
query_state_inclusive_block(tx, contract_ca, key, &parent_addr)
}
pub fn query_state_inclusive_solution_set(
conn: &Connection,
contract_ca: &ContentAddress,
key: &Key,
block_address: &ContentAddress,
solution_set_index: u64,
) -> Result<Option<Value>, QueryError> {
let mut stmt = conn.prepare(sql::query::QUERY_STATE_BLOCK_ADDRESS)?;
let value_blob: Option<(Option<Vec<u8>>, Word)> = stmt
.query_row(
named_params! {
":contract_ca": contract_ca.0,
":key": blob_from_words(key),
":block_address": block_address.0,
":solution_set_index": Some(solution_set_index),
},
|row| {
let value = row.get("found_value")?;
let number = row.get("number")?;
Ok((value, number))
},
)
.optional()?;
match value_blob {
None => Ok(None),
Some((Some(value_blob), _)) => Ok(Some(words_from_blob(&value_blob))),
Some((None, block_number)) => {
super::finalized::query_state_inclusive_block(conn, contract_ca, key, block_number)
}
}
}
pub fn query_state_exclusive_solution_set(
tx: &Transaction,
contract_ca: &ContentAddress,
key: &Key,
block_address: &ContentAddress,
solution_set_index: u64,
) -> Result<Option<Value>, QueryError> {
match solution_set_index.checked_sub(1) {
Some(solution_set_index) => query_state_inclusive_solution_set(
tx,
contract_ca,
key,
block_address,
solution_set_index,
),
None => query_state_exclusive_block(tx, contract_ca, key, block_address),
}
}