197 lines
6.3 KiB
Rust
197 lines
6.3 KiB
Rust
// file: kb_lib/src/db/queries/pair_analytic_signal.rs
|
|
|
|
//! Queries for `k_sol_pair_analytic_signals`.
|
|
|
|
/// Inserts or updates one pair-analytic-signal row and returns its stable internal id.
|
|
pub async fn query_pair_analytic_signals_upsert(
|
|
database: &crate::Database,
|
|
dto: &crate::PairAnalyticSignalDto,
|
|
) -> Result<i64, crate::Error> {
|
|
let signal_value_json_result = serde_json::to_string(&dto.signal_value);
|
|
let signal_value_json = match signal_value_json_result {
|
|
Ok(signal_value_json) => signal_value_json,
|
|
Err(error) => {
|
|
return Err(crate::Error::Db(format!(
|
|
"cannot serialize pair analytic signal payload: {}",
|
|
error
|
|
)));
|
|
},
|
|
};
|
|
match database.connection() {
|
|
crate::DatabaseConnection::Sqlite(pool) => {
|
|
let query_result = sqlx::query(
|
|
r#"
|
|
INSERT INTO k_sol_pair_analytic_signals (
|
|
pair_id,
|
|
signal_kind,
|
|
severity,
|
|
timeframe_seconds,
|
|
bucket_start_unix,
|
|
score,
|
|
signal_value_json,
|
|
first_transaction_id,
|
|
last_transaction_id,
|
|
created_at,
|
|
updated_at
|
|
)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
ON CONFLICT(pair_id, signal_kind, timeframe_seconds, bucket_start_unix) DO UPDATE SET
|
|
severity = excluded.severity,
|
|
score = excluded.score,
|
|
signal_value_json = excluded.signal_value_json,
|
|
last_transaction_id = excluded.last_transaction_id,
|
|
updated_at = excluded.updated_at
|
|
"#,
|
|
)
|
|
.bind(dto.pair_id)
|
|
.bind(dto.signal_kind.clone())
|
|
.bind(dto.severity.to_i16())
|
|
.bind(dto.timeframe_seconds)
|
|
.bind(dto.bucket_start_unix)
|
|
.bind(dto.score)
|
|
.bind(signal_value_json)
|
|
.bind(dto.first_transaction_id)
|
|
.bind(dto.last_transaction_id)
|
|
.bind(dto.created_at.to_rfc3339())
|
|
.bind(dto.updated_at.to_rfc3339())
|
|
.execute(pool)
|
|
.await;
|
|
if let Err(error) = query_result {
|
|
return Err(crate::Error::Db(format!(
|
|
"cannot upsert k_sol_pair_analytic_signals on sqlite: {}",
|
|
error
|
|
)));
|
|
}
|
|
let id_result = sqlx::query_scalar::<sqlx::Sqlite, i64>(
|
|
r#"
|
|
SELECT id
|
|
FROM k_sol_pair_analytic_signals
|
|
WHERE pair_id = ? AND signal_kind = ? AND timeframe_seconds = ? AND bucket_start_unix = ?
|
|
LIMIT 1
|
|
"#,
|
|
)
|
|
.bind(dto.pair_id)
|
|
.bind(dto.signal_kind.clone())
|
|
.bind(dto.timeframe_seconds)
|
|
.bind(dto.bucket_start_unix)
|
|
.fetch_one(pool)
|
|
.await;
|
|
match id_result {
|
|
Ok(id) => return Ok(id),
|
|
Err(error) => {
|
|
return Err(crate::Error::Db(format!(
|
|
"cannot fetch k_sol_pair_analytic_signals id on sqlite: {}",
|
|
error
|
|
)));
|
|
},
|
|
}
|
|
},
|
|
}
|
|
}
|
|
|
|
/// Returns one pair-analytic-signal row identified by its key, if it exists.
|
|
pub async fn query_pair_analytic_signals_get_by_key(
|
|
database: &crate::Database,
|
|
pair_id: i64,
|
|
signal_kind: &str,
|
|
timeframe_seconds: i64,
|
|
bucket_start_unix: i64,
|
|
) -> Result<std::option::Option<crate::PairAnalyticSignalDto>, crate::Error> {
|
|
match database.connection() {
|
|
crate::DatabaseConnection::Sqlite(pool) => {
|
|
let query_result = sqlx::query_as::<sqlx::Sqlite, crate::PairAnalyticSignalEntity>(
|
|
r#"
|
|
SELECT
|
|
id,
|
|
pair_id,
|
|
signal_kind,
|
|
severity,
|
|
timeframe_seconds,
|
|
bucket_start_unix,
|
|
score,
|
|
signal_value_json,
|
|
first_transaction_id,
|
|
last_transaction_id,
|
|
created_at,
|
|
updated_at
|
|
FROM k_sol_pair_analytic_signals
|
|
WHERE pair_id = ? AND signal_kind = ? AND timeframe_seconds = ? AND bucket_start_unix = ?
|
|
LIMIT 1
|
|
"#,
|
|
)
|
|
.bind(pair_id)
|
|
.bind(signal_kind)
|
|
.bind(timeframe_seconds)
|
|
.bind(bucket_start_unix)
|
|
.fetch_optional(pool)
|
|
.await;
|
|
let entity_option = match query_result {
|
|
Ok(entity_option) => entity_option,
|
|
Err(error) => {
|
|
return Err(crate::Error::Db(format!(
|
|
"cannot read k_sol_pair_analytic_signals by key on sqlite: {}",
|
|
error
|
|
)));
|
|
},
|
|
};
|
|
match entity_option {
|
|
Some(entity) => return crate::PairAnalyticSignalDto::try_from(entity).map(Some),
|
|
None => return Ok(None),
|
|
}
|
|
},
|
|
}
|
|
}
|
|
|
|
/// Lists all pair-analytic signals for one pair ordered by key.
|
|
pub async fn query_pair_analytic_signals_list_by_pair_id(
|
|
database: &crate::Database,
|
|
pair_id: i64,
|
|
) -> Result<std::vec::Vec<crate::PairAnalyticSignalDto>, crate::Error> {
|
|
match database.connection() {
|
|
crate::DatabaseConnection::Sqlite(pool) => {
|
|
let query_result = sqlx::query_as::<sqlx::Sqlite, crate::PairAnalyticSignalEntity>(
|
|
r#"
|
|
SELECT
|
|
id,
|
|
pair_id,
|
|
signal_kind,
|
|
severity,
|
|
timeframe_seconds,
|
|
bucket_start_unix,
|
|
score,
|
|
signal_value_json,
|
|
first_transaction_id,
|
|
last_transaction_id,
|
|
created_at,
|
|
updated_at
|
|
FROM k_sol_pair_analytic_signals
|
|
WHERE pair_id = ?
|
|
ORDER BY timeframe_seconds ASC, bucket_start_unix ASC, signal_kind ASC, id ASC
|
|
"#,
|
|
)
|
|
.bind(pair_id)
|
|
.fetch_all(pool)
|
|
.await;
|
|
let entities = match query_result {
|
|
Ok(entities) => entities,
|
|
Err(error) => {
|
|
return Err(crate::Error::Db(format!(
|
|
"cannot list k_sol_pair_analytic_signals by pair_id '{}' on sqlite: {}",
|
|
pair_id, error
|
|
)));
|
|
},
|
|
};
|
|
let mut dtos = std::vec::Vec::new();
|
|
for entity in entities {
|
|
let dto_result = crate::PairAnalyticSignalDto::try_from(entity);
|
|
let dto = match dto_result {
|
|
Ok(dto) => dto,
|
|
Err(error) => return Err(error),
|
|
};
|
|
dtos.push(dto);
|
|
}
|
|
return Ok(dtos);
|
|
},
|
|
}
|
|
}
|