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