mirror of
https://github.com/scsibug/nostr-rs-relay.git
synced 2024-11-21 16:59:06 -05:00
refactor: drop hexrange
Signed-off-by: Greg Heartsfield <scsibug@imap.cc>
This commit is contained in:
parent
971889f9a6
commit
9c86f03902
159
src/hexrange.rs
159
src/hexrange.rs
|
@ -1,159 +0,0 @@
|
||||||
//! Utilities for searching hexadecimal
|
|
||||||
use crate::utils::is_hex;
|
|
||||||
use hex;
|
|
||||||
|
|
||||||
/// Types of hexadecimal queries.
|
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone)]
|
|
||||||
pub enum HexSearch {
|
|
||||||
// when no range is needed, exact 32-byte
|
|
||||||
Exact(Vec<u8>),
|
|
||||||
// lower (inclusive) and upper range (exclusive)
|
|
||||||
Range(Vec<u8>, Vec<u8>),
|
|
||||||
// lower bound only, upper bound is MAX inclusive
|
|
||||||
LowerOnly(Vec<u8>),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if a string contains only f chars
|
|
||||||
fn is_all_fs(s: &str) -> bool {
|
|
||||||
s.chars().all(|x| x == 'f' || x == 'F')
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Find the next hex sequence greater than the argument.
|
|
||||||
#[must_use]
|
|
||||||
pub fn hex_range(s: &str) -> Option<HexSearch> {
|
|
||||||
let mut hash_base = s.to_owned();
|
|
||||||
if !is_hex(&hash_base) || hash_base.len() > 64 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
if hash_base.len() == 64 {
|
|
||||||
return Some(HexSearch::Exact(hex::decode(&hash_base).ok()?));
|
|
||||||
}
|
|
||||||
// if s is odd, add a zero
|
|
||||||
let mut odd = hash_base.len() % 2 != 0;
|
|
||||||
if odd {
|
|
||||||
// extend the string to make it even
|
|
||||||
hash_base.push('0');
|
|
||||||
}
|
|
||||||
let base = hex::decode(hash_base).ok()?;
|
|
||||||
// check for all ff's
|
|
||||||
if is_all_fs(s) {
|
|
||||||
// there is no higher bound, we only want to search for blobs greater than this.
|
|
||||||
return Some(HexSearch::LowerOnly(base));
|
|
||||||
}
|
|
||||||
|
|
||||||
// return a range
|
|
||||||
let mut upper = base.clone();
|
|
||||||
let mut byte_len = upper.len();
|
|
||||||
|
|
||||||
// for odd strings, we made them longer, but we want to increment the upper char (+16).
|
|
||||||
// we know we can do this without overflowing because we explicitly set the bottom half to 0's.
|
|
||||||
while byte_len > 0 {
|
|
||||||
byte_len -= 1;
|
|
||||||
// check if byte can be incremented, or if we need to carry.
|
|
||||||
let b = upper[byte_len];
|
|
||||||
if b == u8::MAX {
|
|
||||||
// reset and carry
|
|
||||||
upper[byte_len] = 0;
|
|
||||||
} else if odd {
|
|
||||||
// check if first char in this byte is NOT 'f'
|
|
||||||
if b < 240 {
|
|
||||||
// bump up the first character in this byte
|
|
||||||
upper[byte_len] = b + 16;
|
|
||||||
// increment done, stop iterating through the vec
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// if it is 'f', reset the byte to 0 and do a carry
|
|
||||||
// reset and carry
|
|
||||||
upper[byte_len] = 0;
|
|
||||||
// done with odd logic, so don't repeat this
|
|
||||||
odd = false;
|
|
||||||
} else {
|
|
||||||
// bump up the first character in this byte
|
|
||||||
upper[byte_len] = b + 1;
|
|
||||||
// increment done, stop iterating
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(HexSearch::Range(base, upper))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use crate::error::Result;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn hex_range_exact() -> Result<()> {
|
|
||||||
let hex = "abcdef00abcdef00abcdef00abcdef00abcdef00abcdef00abcdef00abcdef00";
|
|
||||||
let r = hex_range(hex);
|
|
||||||
assert_eq!(
|
|
||||||
r,
|
|
||||||
Some(HexSearch::Exact(hex::decode(hex).expect("invalid hex")))
|
|
||||||
);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn hex_full_range() -> Result<()> {
|
|
||||||
let hex = "aaaa";
|
|
||||||
let hex_upper = "aaab";
|
|
||||||
let r = hex_range(hex);
|
|
||||||
assert_eq!(
|
|
||||||
r,
|
|
||||||
Some(HexSearch::Range(
|
|
||||||
hex::decode(hex).expect("invalid hex"),
|
|
||||||
hex::decode(hex_upper).expect("invalid hex")
|
|
||||||
))
|
|
||||||
);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn hex_full_range_odd() -> Result<()> {
|
|
||||||
let r = hex_range("abc");
|
|
||||||
assert_eq!(
|
|
||||||
r,
|
|
||||||
Some(HexSearch::Range(
|
|
||||||
hex::decode("abc0").expect("invalid hex"),
|
|
||||||
hex::decode("abd0").expect("invalid hex")
|
|
||||||
))
|
|
||||||
);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn hex_full_range_odd_end_f() -> Result<()> {
|
|
||||||
let r = hex_range("abf");
|
|
||||||
assert_eq!(
|
|
||||||
r,
|
|
||||||
Some(HexSearch::Range(
|
|
||||||
hex::decode("abf0").expect("invalid hex"),
|
|
||||||
hex::decode("ac00").expect("invalid hex")
|
|
||||||
))
|
|
||||||
);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn hex_no_upper() -> Result<()> {
|
|
||||||
let r = hex_range("ffff");
|
|
||||||
assert_eq!(
|
|
||||||
r,
|
|
||||||
Some(HexSearch::LowerOnly(
|
|
||||||
hex::decode("ffff").expect("invalid hex")
|
|
||||||
))
|
|
||||||
);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn hex_no_upper_odd() -> Result<()> {
|
|
||||||
let r = hex_range("fff");
|
|
||||||
assert_eq!(
|
|
||||||
r,
|
|
||||||
Some(HexSearch::LowerOnly(
|
|
||||||
hex::decode("fff0").expect("invalid hex")
|
|
||||||
))
|
|
||||||
);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,7 +6,6 @@ pub mod db;
|
||||||
pub mod delegation;
|
pub mod delegation;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod event;
|
pub mod event;
|
||||||
pub mod hexrange;
|
|
||||||
pub mod info;
|
pub mod info;
|
||||||
pub mod nauthz;
|
pub mod nauthz;
|
||||||
pub mod nip05;
|
pub mod nip05;
|
||||||
|
|
|
@ -14,7 +14,6 @@ use sqlx::{Error, Execute, FromRow, Postgres, QueryBuilder, Row};
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use crate::error;
|
use crate::error;
|
||||||
use crate::hexrange::{hex_range, HexSearch};
|
|
||||||
use crate::repo::postgres_migration::run_migrations;
|
use crate::repo::postgres_migration::run_migrations;
|
||||||
use crate::server::NostrMetrics;
|
use crate::server::NostrMetrics;
|
||||||
use crate::utils::{self, is_hex, is_lower_hex};
|
use crate::utils::{self, is_hex, is_lower_hex};
|
||||||
|
@ -60,8 +59,7 @@ async fn cleanup_expired(conn: PostgresPool, frequency: Duration) -> Result<()>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -151,19 +149,19 @@ impl NostrRepo for PostgresRepo {
|
||||||
VALUES($1, $2, $3, $4, $5, $6, $7)
|
VALUES($1, $2, $3, $4, $5, $6, $7)
|
||||||
ON CONFLICT (id) DO NOTHING"#,
|
ON CONFLICT (id) DO NOTHING"#,
|
||||||
)
|
)
|
||||||
.bind(&id_blob)
|
.bind(&id_blob)
|
||||||
.bind(&pubkey_blob)
|
.bind(&pubkey_blob)
|
||||||
.bind(Utc.timestamp_opt(e.created_at as i64, 0).unwrap())
|
.bind(Utc.timestamp_opt(e.created_at as i64, 0).unwrap())
|
||||||
.bind(
|
.bind(
|
||||||
e.expiration()
|
e.expiration()
|
||||||
.and_then(|x| Utc.timestamp_opt(x as i64, 0).latest()),
|
.and_then(|x| Utc.timestamp_opt(x as i64, 0).latest()),
|
||||||
)
|
)
|
||||||
.bind(e.kind as i64)
|
.bind(e.kind as i64)
|
||||||
.bind(event_str.into_bytes())
|
.bind(event_str.into_bytes())
|
||||||
.bind(delegator_blob)
|
.bind(delegator_blob)
|
||||||
.execute(&mut tx)
|
.execute(&mut tx)
|
||||||
.await?
|
.await?
|
||||||
.rows_affected();
|
.rows_affected();
|
||||||
|
|
||||||
if ins_count == 0 {
|
if ins_count == 0 {
|
||||||
// if the event was a duplicate, no need to insert event or
|
// if the event was a duplicate, no need to insert event or
|
||||||
|
@ -283,10 +281,10 @@ ON CONFLICT (id) DO NOTHING"#,
|
||||||
LEFT JOIN tag t ON e.id = t.event_id \
|
LEFT JOIN tag t ON e.id = t.event_id \
|
||||||
WHERE e.pub_key = $1 AND t.\"name\" = 'e' AND e.kind = 5 AND t.value = $2 LIMIT 1",
|
WHERE e.pub_key = $1 AND t.\"name\" = 'e' AND e.kind = 5 AND t.value = $2 LIMIT 1",
|
||||||
)
|
)
|
||||||
.bind(&pubkey_blob)
|
.bind(&pubkey_blob)
|
||||||
.bind(&id_blob)
|
.bind(&id_blob)
|
||||||
.fetch_optional(&mut tx)
|
.fetch_optional(&mut tx)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// check if a the query returned a result, meaning we should
|
// check if a the query returned a result, meaning we should
|
||||||
// hid the current event
|
// hid the current event
|
||||||
|
@ -577,10 +575,10 @@ ON CONFLICT (id) DO NOTHING"#,
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
"UPDATE account SET is_admitted = TRUE, balance = balance - $1 WHERE pubkey = $2",
|
"UPDATE account SET is_admitted = TRUE, balance = balance - $1 WHERE pubkey = $2",
|
||||||
)
|
)
|
||||||
.bind(admission_cost as i64)
|
.bind(admission_cost as i64)
|
||||||
.bind(pub_key)
|
.bind(pub_key)
|
||||||
.execute(&self.conn_write)
|
.execute(&self.conn_write)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,6 +724,7 @@ fn query_from_filter(f: &ReqFilter) -> Option<QueryBuilder<Postgres>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut query = QueryBuilder::new("SELECT e.\"content\", e.created_at FROM \"event\" e WHERE ");
|
let mut query = QueryBuilder::new("SELECT e.\"content\", e.created_at FROM \"event\" e WHERE ");
|
||||||
|
|
||||||
// This tracks whether we need to push a prefix AND before adding another clause
|
// This tracks whether we need to push a prefix AND before adding another clause
|
||||||
let mut push_and = false;
|
let mut push_and = false;
|
||||||
// Query for "authors", allowing prefix matches
|
// Query for "authors", allowing prefix matches
|
||||||
|
@ -736,63 +735,19 @@ fn query_from_filter(f: &ReqFilter) -> Option<QueryBuilder<Postgres>> {
|
||||||
if auth_vec.is_empty() {
|
if auth_vec.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
query.push("(");
|
query.push("(e.pub_key in (");
|
||||||
|
|
||||||
// shortcut authors into "IN" query
|
let mut pk_sep = query.separated(", ");
|
||||||
let any_is_range = auth_vec.iter().any(|pk| pk.len() != 64);
|
for pk in auth_vec.iter() {
|
||||||
if !any_is_range {
|
pk_sep.push_bind(hex::decode(pk).ok());
|
||||||
query.push("e.pub_key in (");
|
|
||||||
let mut pk_sep = query.separated(", ");
|
|
||||||
for pk in auth_vec.iter() {
|
|
||||||
pk_sep.push_bind(hex::decode(pk).ok());
|
|
||||||
}
|
|
||||||
query.push(") OR e.delegated_by in (");
|
|
||||||
let mut pk_delegated_sep = query.separated(", ");
|
|
||||||
for pk in auth_vec.iter() {
|
|
||||||
pk_delegated_sep.push_bind(hex::decode(pk).ok());
|
|
||||||
}
|
|
||||||
query.push(")");
|
|
||||||
push_and = true;
|
|
||||||
} else {
|
|
||||||
let mut range_authors = query.separated(" OR ");
|
|
||||||
for auth in auth_vec {
|
|
||||||
match hex_range(auth) {
|
|
||||||
Some(HexSearch::Exact(ex)) => {
|
|
||||||
range_authors
|
|
||||||
.push("(e.pub_key = ")
|
|
||||||
.push_bind_unseparated(ex.clone())
|
|
||||||
.push_unseparated(" OR e.delegated_by = ")
|
|
||||||
.push_bind_unseparated(ex)
|
|
||||||
.push_unseparated(")");
|
|
||||||
}
|
|
||||||
Some(HexSearch::Range(lower, upper)) => {
|
|
||||||
range_authors
|
|
||||||
.push("((e.pub_key > ")
|
|
||||||
.push_bind_unseparated(lower.clone())
|
|
||||||
.push_unseparated(" AND e.pub_key < ")
|
|
||||||
.push_bind_unseparated(upper.clone())
|
|
||||||
.push_unseparated(") OR (e.delegated_by > ")
|
|
||||||
.push_bind_unseparated(lower)
|
|
||||||
.push_unseparated(" AND e.delegated_by < ")
|
|
||||||
.push_bind_unseparated(upper)
|
|
||||||
.push_unseparated("))");
|
|
||||||
}
|
|
||||||
Some(HexSearch::LowerOnly(lower)) => {
|
|
||||||
range_authors
|
|
||||||
.push("(e.pub_key > ")
|
|
||||||
.push_bind_unseparated(lower.clone())
|
|
||||||
.push_unseparated(" OR e.delegated_by > ")
|
|
||||||
.push_bind_unseparated(lower)
|
|
||||||
.push_unseparated(")");
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
info!("Could not parse hex range from author {:?}", auth);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
push_and = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
query.push(")");
|
query.push(") OR e.delegated_by in (");
|
||||||
|
let mut pk_delegated_sep = query.separated(", ");
|
||||||
|
for pk in auth_vec.iter() {
|
||||||
|
pk_delegated_sep.push_bind(hex::decode(pk).ok());
|
||||||
|
}
|
||||||
|
push_and = true;
|
||||||
|
query.push("))");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query for Kind
|
// Query for Kind
|
||||||
|
@ -813,7 +768,7 @@ fn query_from_filter(f: &ReqFilter) -> Option<QueryBuilder<Postgres>> {
|
||||||
query.push(")");
|
query.push(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query for event, allowing prefix matches
|
// Query for event,
|
||||||
if let Some(id_vec) = &f.ids {
|
if let Some(id_vec) = &f.ids {
|
||||||
// filter out non-hex values
|
// filter out non-hex values
|
||||||
let id_vec: Vec<&String> = id_vec.iter().filter(|a| is_hex(a)).collect();
|
let id_vec: Vec<&String> = id_vec.iter().filter(|a| is_hex(a)).collect();
|
||||||
|
@ -827,48 +782,12 @@ fn query_from_filter(f: &ReqFilter) -> Option<QueryBuilder<Postgres>> {
|
||||||
}
|
}
|
||||||
push_and = true;
|
push_and = true;
|
||||||
|
|
||||||
// shortcut ids into "IN" query
|
query.push("id in (");
|
||||||
let any_is_range = id_vec.iter().any(|pk| pk.len() != 64);
|
let mut sep = query.separated(", ");
|
||||||
if !any_is_range {
|
for id in id_vec.iter() {
|
||||||
query.push("id in (");
|
sep.push_bind(hex::decode(id).ok());
|
||||||
let mut sep = query.separated(", ");
|
|
||||||
for id in id_vec.iter() {
|
|
||||||
sep.push_bind(hex::decode(id).ok());
|
|
||||||
}
|
|
||||||
query.push(")");
|
|
||||||
} else {
|
|
||||||
// take each author and convert to a hex search
|
|
||||||
let mut id_query = query.separated(" OR ");
|
|
||||||
for id in id_vec {
|
|
||||||
match hex_range(id) {
|
|
||||||
Some(HexSearch::Exact(ex)) => {
|
|
||||||
id_query
|
|
||||||
.push("(id = ")
|
|
||||||
.push_bind_unseparated(ex)
|
|
||||||
.push_unseparated(")");
|
|
||||||
}
|
|
||||||
Some(HexSearch::Range(lower, upper)) => {
|
|
||||||
id_query
|
|
||||||
.push("(id > ")
|
|
||||||
.push_bind_unseparated(lower)
|
|
||||||
.push_unseparated(" AND id < ")
|
|
||||||
.push_bind_unseparated(upper)
|
|
||||||
.push_unseparated(")");
|
|
||||||
}
|
|
||||||
Some(HexSearch::LowerOnly(lower)) => {
|
|
||||||
id_query
|
|
||||||
.push("(id > ")
|
|
||||||
.push_bind_unseparated(lower)
|
|
||||||
.push_unseparated(")");
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
info!("Could not parse hex range from id {:?}", id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
query.push("))");
|
||||||
query.push(")");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query for tags
|
// Query for tags
|
||||||
|
@ -888,7 +807,8 @@ fn query_from_filter(f: &ReqFilter) -> Option<QueryBuilder<Postgres>> {
|
||||||
if push_or {
|
if push_or {
|
||||||
query.push(" OR ");
|
query.push(" OR ");
|
||||||
}
|
}
|
||||||
query.push("(t.\"name\" = ")
|
query
|
||||||
|
.push("(t.\"name\" = ")
|
||||||
.push_bind(key.to_string())
|
.push_bind(key.to_string())
|
||||||
.push(" AND (");
|
.push(" AND (");
|
||||||
|
|
||||||
|
@ -898,8 +818,7 @@ fn query_from_filter(f: &ReqFilter) -> Option<QueryBuilder<Postgres>> {
|
||||||
query.push("value in (");
|
query.push("value in (");
|
||||||
// plain value match first
|
// plain value match first
|
||||||
let mut tag_query = query.separated(", ");
|
let mut tag_query = query.separated(", ");
|
||||||
for v in val.iter()
|
for v in val.iter().filter(|v| !is_lower_hex(v)) {
|
||||||
.filter(|v| !is_lower_hex(v)) {
|
|
||||||
tag_query.push_bind(v.as_bytes());
|
tag_query.push_bind(v.as_bytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -910,8 +829,7 @@ fn query_from_filter(f: &ReqFilter) -> Option<QueryBuilder<Postgres>> {
|
||||||
query.push("value_hex in (");
|
query.push("value_hex in (");
|
||||||
// plain value match first
|
// plain value match first
|
||||||
let mut tag_query = query.separated(", ");
|
let mut tag_query = query.separated(", ");
|
||||||
for v in val.iter()
|
for v in val.iter().filter(|v| v.len() % 2 == 0 && is_lower_hex(v)) {
|
||||||
.filter(|v| v.len() % 2 == 0 && is_lower_hex(v)) {
|
|
||||||
tag_query.push_bind(hex::decode(v).ok());
|
tag_query.push_bind(hex::decode(v).ok());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -988,11 +906,10 @@ impl FromRow<'_, PgRow> for VerificationRecord {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::collections::{HashMap, HashSet};
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_gen_tag_value_hex() {
|
fn test_query_gen_tag_value_hex() {
|
||||||
|
@ -1001,11 +918,16 @@ mod tests {
|
||||||
kinds: Some(vec![1000]),
|
kinds: Some(vec![1000]),
|
||||||
since: None,
|
since: None,
|
||||||
until: None,
|
until: None,
|
||||||
authors: Some(vec!["84de35e2584d2b144aae823c9ed0b0f3deda09648530b93d1a2a146d1dea9864".to_owned()]),
|
authors: Some(vec![
|
||||||
|
"84de35e2584d2b144aae823c9ed0b0f3deda09648530b93d1a2a146d1dea9864".to_owned(),
|
||||||
|
]),
|
||||||
limit: None,
|
limit: None,
|
||||||
tags: Some(HashMap::from([
|
tags: Some(HashMap::from([(
|
||||||
('p', HashSet::from(["63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed".to_owned()]))
|
'p',
|
||||||
])),
|
HashSet::from([
|
||||||
|
"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed".to_owned(),
|
||||||
|
]),
|
||||||
|
)])),
|
||||||
force_no_match: false,
|
force_no_match: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1020,11 +942,11 @@ mod tests {
|
||||||
kinds: Some(vec![1000]),
|
kinds: Some(vec![1000]),
|
||||||
since: None,
|
since: None,
|
||||||
until: None,
|
until: None,
|
||||||
authors: Some(vec!["84de35e2584d2b144aae823c9ed0b0f3deda09648530b93d1a2a146d1dea9864".to_owned()]),
|
authors: Some(vec![
|
||||||
|
"84de35e2584d2b144aae823c9ed0b0f3deda09648530b93d1a2a146d1dea9864".to_owned(),
|
||||||
|
]),
|
||||||
limit: None,
|
limit: None,
|
||||||
tags: Some(HashMap::from([
|
tags: Some(HashMap::from([('d', HashSet::from(["test".to_owned()]))])),
|
||||||
('d', HashSet::from(["test".to_owned()]))
|
|
||||||
])),
|
|
||||||
force_no_match: false,
|
force_no_match: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1039,11 +961,17 @@ mod tests {
|
||||||
kinds: Some(vec![1000]),
|
kinds: Some(vec![1000]),
|
||||||
since: None,
|
since: None,
|
||||||
until: None,
|
until: None,
|
||||||
authors: Some(vec!["84de35e2584d2b144aae823c9ed0b0f3deda09648530b93d1a2a146d1dea9864".to_owned()]),
|
authors: Some(vec![
|
||||||
|
"84de35e2584d2b144aae823c9ed0b0f3deda09648530b93d1a2a146d1dea9864".to_owned(),
|
||||||
|
]),
|
||||||
limit: None,
|
limit: None,
|
||||||
tags: Some(HashMap::from([
|
tags: Some(HashMap::from([(
|
||||||
('d', HashSet::from(["test".to_owned(), "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed".to_owned()]))
|
'd',
|
||||||
])),
|
HashSet::from([
|
||||||
|
"test".to_owned(),
|
||||||
|
"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed".to_owned(),
|
||||||
|
]),
|
||||||
|
)])),
|
||||||
force_no_match: false,
|
force_no_match: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1062,7 +990,7 @@ mod tests {
|
||||||
limit: None,
|
limit: None,
|
||||||
tags: Some(HashMap::from([
|
tags: Some(HashMap::from([
|
||||||
('d', HashSet::from(["follow".to_owned()])),
|
('d', HashSet::from(["follow".to_owned()])),
|
||||||
('t', HashSet::from(["siamstr".to_owned()]))
|
('t', HashSet::from(["siamstr".to_owned()])),
|
||||||
])),
|
])),
|
||||||
force_no_match: false,
|
force_no_match: false,
|
||||||
};
|
};
|
||||||
|
@ -1079,11 +1007,9 @@ mod tests {
|
||||||
until: None,
|
until: None,
|
||||||
authors: None,
|
authors: None,
|
||||||
limit: None,
|
limit: None,
|
||||||
tags: Some(HashMap::from([
|
tags: Some(HashMap::from([('a', HashSet::new())])),
|
||||||
('a', HashSet::new())
|
|
||||||
])),
|
|
||||||
force_no_match: false,
|
force_no_match: false,
|
||||||
};
|
};
|
||||||
assert!(query_from_filter(&filter).is_none());
|
assert!(query_from_filter(&filter).is_none());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,6 @@ use crate::config::Settings;
|
||||||
use crate::db::QueryResult;
|
use crate::db::QueryResult;
|
||||||
use crate::error::{Error::SqlError, Result};
|
use crate::error::{Error::SqlError, Result};
|
||||||
use crate::event::{single_char_tagname, Event};
|
use crate::event::{single_char_tagname, Event};
|
||||||
use crate::hexrange::hex_range;
|
|
||||||
use crate::hexrange::HexSearch;
|
|
||||||
use crate::nip05::{Nip05Name, VerificationRecord};
|
use crate::nip05::{Nip05Name, VerificationRecord};
|
||||||
use crate::payment::{InvoiceInfo, InvoiceStatus};
|
use crate::payment::{InvoiceInfo, InvoiceStatus};
|
||||||
use crate::repo::sqlite_migration::{upgrade_db, STARTUP_SQL};
|
use crate::repo::sqlite_migration::{upgrade_db, STARTUP_SQL};
|
||||||
|
@ -994,24 +992,8 @@ fn query_from_filter(f: &ReqFilter) -> (String, Vec<Box<dyn ToSql>>, Option<Stri
|
||||||
// take each author and convert to a hexsearch
|
// take each author and convert to a hexsearch
|
||||||
let mut auth_searches: Vec<String> = vec![];
|
let mut auth_searches: Vec<String> = vec![];
|
||||||
for auth in authvec {
|
for auth in authvec {
|
||||||
match hex_range(auth) {
|
auth_searches.push("author=?".to_owned());
|
||||||
Some(HexSearch::Exact(ex)) => {
|
params.push(Box::new(auth.clone()));
|
||||||
auth_searches.push("author=?".to_owned());
|
|
||||||
params.push(Box::new(ex));
|
|
||||||
}
|
|
||||||
Some(HexSearch::Range(lower, upper)) => {
|
|
||||||
auth_searches.push("(author>? AND author<?)".to_owned());
|
|
||||||
params.push(Box::new(lower));
|
|
||||||
params.push(Box::new(upper));
|
|
||||||
}
|
|
||||||
Some(HexSearch::LowerOnly(lower)) => {
|
|
||||||
auth_searches.push("author>?".to_owned());
|
|
||||||
params.push(Box::new(lower));
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
trace!("Could not parse hex range from author {:?}", auth);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if !authvec.is_empty() {
|
if !authvec.is_empty() {
|
||||||
let auth_clause = format!("({})", auth_searches.join(" OR "));
|
let auth_clause = format!("({})", auth_searches.join(" OR "));
|
||||||
|
@ -1032,24 +1014,8 @@ fn query_from_filter(f: &ReqFilter) -> (String, Vec<Box<dyn ToSql>>, Option<Stri
|
||||||
// take each author and convert to a hexsearch
|
// take each author and convert to a hexsearch
|
||||||
let mut id_searches: Vec<String> = vec![];
|
let mut id_searches: Vec<String> = vec![];
|
||||||
for id in idvec {
|
for id in idvec {
|
||||||
match hex_range(id) {
|
id_searches.push("event_hash=?".to_owned());
|
||||||
Some(HexSearch::Exact(ex)) => {
|
params.push(Box::new(id.clone()));
|
||||||
id_searches.push("event_hash=?".to_owned());
|
|
||||||
params.push(Box::new(ex));
|
|
||||||
}
|
|
||||||
Some(HexSearch::Range(lower, upper)) => {
|
|
||||||
id_searches.push("(event_hash>? AND event_hash<?)".to_owned());
|
|
||||||
params.push(Box::new(lower));
|
|
||||||
params.push(Box::new(upper));
|
|
||||||
}
|
|
||||||
Some(HexSearch::LowerOnly(lower)) => {
|
|
||||||
id_searches.push("event_hash>?".to_owned());
|
|
||||||
params.push(Box::new(lower));
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
info!("Could not parse hex range from id {:?}", id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if idvec.is_empty() {
|
if idvec.is_empty() {
|
||||||
// if the ids list was empty, we should never return
|
// if the ids list was empty, we should never return
|
||||||
|
|
Loading…
Reference in New Issue
Block a user