Consider blockheight before timestamp

This commit is contained in:
Jakob Notland 2025-09-17 12:05:24 +02:00
parent 46462284e8
commit af97a75540

View file

@ -253,14 +253,12 @@ fn add_column_if_missing(conn: &Connection, table: &str, column: &str, decl: &st
Ok(())
}
fn table_has_column(conn: &Connection, table: &str, column: &str) -> Result<bool> {
fn table_has_column(conn: &Connection, table: &str, column: &str) -> anyhow::Result<bool> {
let mut stmt = conn.prepare(&format!("PRAGMA table_info({table});"))?;
let mut rows = stmt.query([])?;
while let Some(row) = rows.next()? {
let name: String = row.get(1)?;
if name.eq_ignore_ascii_case(column) {
return Ok(true);
}
if name.eq_ignore_ascii_case(column) { return Ok(true); }
}
Ok(false)
}
@ -296,25 +294,48 @@ pub fn cache_first_pool_ts_if_empty(conn: &Connection, token_id: &str, ts: i64)
pub fn db_first_pool_creation_row(
conn: &Connection,
token_id: &str,
) -> Result<Option<FirstPoolInfo>> {
// Prefer height when available; otherwise fall back to timestamp-only ordering.
let has_height = table_has_column(conn, "tx", "block_height")?;
let sql = if has_height {
) -> anyhow::Result<Option<FirstPoolInfo>> {
let has_tx_height = table_has_column(conn, "tx", "block_height")?;
let has_blockhash = table_has_column(conn, "tx", "blockhash")?;
let has_headers_key = table_has_column(conn, "headers", "key")?;
let has_headers_ht = table_has_column(conn, "headers", "height")?;
let sql = if has_tx_height {
// Native height column present
r#"
SELECT p.creation_utxo, uf.txid, t.effective_timestamp, t.block_height
SELECT p.creation_utxo, uf.txid, t.effective_timestamp, t.block_height AS block_height
FROM pool AS p
JOIN utxo_funding AS uf ON uf.new_utxo_hash = p.creation_utxo
JOIN tx AS t ON t.txid = uf.txid
WHERE p.token_id = ?
ORDER BY
(t.block_height IS NULL) ASC,
t.block_height ASC,
(t.block_height IS NULL) ASC, -- confirmed first
t.block_height ASC, -- earliest height
t.effective_timestamp ASC,
uf.txid ASC,
p.creation_utxo ASC
LIMIT 1;
"#
} else if has_blockhash && has_headers_key && has_headers_ht {
// Derive height from headers
r#"
SELECT p.creation_utxo, uf.txid, t.effective_timestamp, h.height AS block_height
FROM pool AS p
JOIN utxo_funding AS uf ON uf.new_utxo_hash = p.creation_utxo
JOIN tx AS t ON t.txid = uf.txid
LEFT JOIN headers AS h ON h.key = t.blockhash
WHERE p.token_id = ?
ORDER BY
(t.blockhash IS NULL) ASC, -- confirmed (has blockhash) first
(h.height IS NULL) ASC, -- known height before unknown
h.height ASC,
t.effective_timestamp ASC,
uf.txid ASC,
p.creation_utxo ASC
LIMIT 1;
"#
} else {
// Timestamp-only fallback
r#"
SELECT p.creation_utxo, uf.txid, t.effective_timestamp, NULL AS block_height
FROM pool AS p
@ -332,10 +353,10 @@ pub fn db_first_pool_creation_row(
let mut stmt = conn.prepare(sql)?;
let mut rows = stmt.query(params![token_id])?;
if let Some(row) = rows.next()? {
let creation_utxo: String = row.get(0)?;
let txid: String = row.get(1)?;
let ts: i64 = row.get(2)?;
let height: Option<i64> = row.get(3)?;
let creation_utxo: String = row.get(0)?;
let txid: String = row.get(1)?;
let ts: i64 = row.get(2)?;
let height: Option<i64> = row.get(3)?;
Ok(Some((creation_utxo, txid, ts, height)))
} else {
Ok(None)