Skip to content

Commit

Permalink
feat: allow returning None for query interfaces (#255) (#256)
Browse files Browse the repository at this point in the history
  • Loading branch information
holtgrewe authored Oct 17, 2023
1 parent dd4eecc commit b4bf349
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 108 deletions.
37 changes: 26 additions & 11 deletions src/clinvar_genes/cli/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,29 @@ fn print_record(
Ok(())
}

/// Query for one gene annotation record.
pub fn query_for_gene(
hgnc_id: &str,
db: &rocksdb::DBWithThreadMode<rocksdb::MultiThreaded>,
cf_data: &Arc<rocksdb::BoundColumnFamily>,
) -> Result<Option<clinvar_genes::pbs::ClinvarPerGeneRecord>, anyhow::Error> {
let raw_value = db
.get_cf(cf_data, hgnc_id.as_bytes())
.map_err(|e| anyhow::anyhow!("error while querying for HGNC ID {}: {}", hgnc_id, e))?;
raw_value
.map(|raw_value| {
clinvar_genes::pbs::ClinvarPerGeneRecord::decode(&mut std::io::Cursor::new(&raw_value))
.map_err(|e| {
anyhow::anyhow!(
"error while decoding clinvar per gene record for HGNC ID {}: {}",
hgnc_id,
e
)
})
})
.transpose()
}

/// Implementation of `gene query` sub command.
pub fn run(common: &common::cli::Args, args: &Args) -> Result<(), anyhow::Error> {
tracing::info!("Starting 'gene query' command");
Expand All @@ -94,19 +117,11 @@ pub fn run(common: &common::cli::Args, args: &Args) -> Result<(), anyhow::Error>
};

tracing::info!("Running query...");
let raw_value = db.get_cf(&cf_data, args.hgnc_id.as_bytes())?;
if let Some(raw_value) = raw_value {
print_record(
&mut out_writer,
args.out_format,
&clinvar_genes::pbs::ClinvarPerGeneRecord::decode(&mut std::io::Cursor::new(
&raw_value,
))?,
)?;
if let Some(record) = query_for_gene(&args.hgnc_id, &db, &cf_data)? {
print_record(&mut out_writer, args.out_format, &record)?;
} else {
tracing::info!("No data found for HGNC ID {}", args.hgnc_id);
tracing::info!("no record found for HGNC ID {:?}", args.hgnc_id);
}

tracing::info!("All done. Have a nice day!");
Ok(())
}
26 changes: 15 additions & 11 deletions src/clinvar_minimal/cli/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ pub fn query_for_variant(
meta: &Meta,
db: &rocksdb::DBWithThreadMode<rocksdb::MultiThreaded>,
cf_data: &Arc<rocksdb::BoundColumnFamily>,
) -> Result<pbs::Record, anyhow::Error> {
) -> Result<Option<pbs::Record>, anyhow::Error> {
// Split off the genome release (checked) and convert to key as used in database.
let query = spdi::Var {
sequence: extract_chrom::from_var(variant, Some(&meta.genome_release))?,
Expand All @@ -113,11 +113,15 @@ pub fn query_for_variant(
let var: keys::Var = query.into();
let key: Vec<u8> = var.into();
let raw_value = db
.get_cf(cf_data, key)?
.ok_or_else(|| anyhow::anyhow!("could not find variant in database"))?;
// Decode via prost.
pbs::Record::decode(&mut std::io::Cursor::new(&raw_value))
.map_err(|e| anyhow::anyhow!("failed to decode record: {}", e))
.get_cf(cf_data, key)
.map_err(|e| anyhow::anyhow!("error while querying for variant {}: {}", variant, e))?;
raw_value
.map(|raw_value| {
// Decode via prost.
pbs::Record::decode(&mut std::io::Cursor::new(&raw_value))
.map_err(|e| anyhow::anyhow!("failed to decode record: {}", e))
})
.transpose()
}

/// Implementation of `tsv query` sub command.
Expand All @@ -141,11 +145,11 @@ pub fn run(common: &common::cli::Args, args: &Args) -> Result<(), anyhow::Error>
tracing::info!("Running query...");
let before_query = std::time::Instant::now();
if let Some(variant) = args.query.variant.as_ref() {
print_record(
&mut out_writer,
args.out_format,
&query_for_variant(variant, &meta, &db, &cf_data)?,
)?;
if let Some(record) = query_for_variant(variant, &meta, &db, &cf_data)? {
print_record(&mut out_writer, args.out_format, &record)?;
} else {
tracing::info!("no record found for variant {:?}", &variant);
}
} else {
let (start, stop) = if let Some(position) = args.query.position.as_ref() {
let position = spdi::Pos {
Expand Down
26 changes: 15 additions & 11 deletions src/dbsnp/cli/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ pub fn query_for_variant(
meta: &Meta,
db: &rocksdb::DBWithThreadMode<rocksdb::MultiThreaded>,
cf_data: &Arc<rocksdb::BoundColumnFamily>,
) -> Result<dbsnp::pbs::Record, anyhow::Error> {
) -> Result<Option<dbsnp::pbs::Record>, anyhow::Error> {
// Split off the genome release (checked) and convert to key as used in database.
let query = spdi::Var {
sequence: extract_chrom::from_var(variant, Some(&meta.genome_release))?,
Expand All @@ -129,11 +129,15 @@ pub fn query_for_variant(
let var: keys::Var = query.into();
let key: Vec<u8> = var.into();
let raw_value = db
.get_cf(cf_data, key)?
.ok_or_else(|| anyhow::anyhow!("could not find variant in database"))?;
// Decode via prost.
dbsnp::pbs::Record::decode(&mut std::io::Cursor::new(&raw_value))
.map_err(|e| anyhow::anyhow!("failed to decode record: {}", e))
.get_cf(cf_data, key)
.map_err(|e| anyhow::anyhow!("error while querying for variant {}: {}", variant, e))?;
raw_value
.map(|raw_value| {
// Decode via prost.
dbsnp::pbs::Record::decode(&mut std::io::Cursor::new(&raw_value))
.map_err(|e| anyhow::anyhow!("failed to decode record: {}", e))
})
.transpose()
}

/// Implementation of `tsv query` sub command.
Expand All @@ -157,11 +161,11 @@ pub fn run(common: &common::cli::Args, args: &Args) -> Result<(), anyhow::Error>
tracing::info!("Running query...");
let before_query = std::time::Instant::now();
if let Some(variant) = args.query.variant.as_ref() {
print_record(
&mut out_writer,
args.out_format,
&query_for_variant(variant, &meta, &db, &cf_data)?,
)?;
if let Some(record) = query_for_variant(variant, &meta, &db, &cf_data)? {
print_record(&mut out_writer, args.out_format, &record)?;
} else {
tracing::info!("no record found for variant {}", variant);
}
} else {
let (start, stop) = if let Some(position) = args.query.position.as_ref() {
let position = spdi::Pos {
Expand Down
70 changes: 51 additions & 19 deletions src/freqs/cli/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,46 +85,58 @@ pub fn open_rocksdb_from_args(
)
}

/// Enumeration of possible result records.
pub enum Record {
/// Record for autosomal variant.
Autosomal(freqs::serialized::auto::Record),
/// Record for gonosomal variant.
Gonosomal(freqs::serialized::xy::Record),
/// Record for mitochondrial variant.
Mitochondrial(freqs::serialized::mt::Record),
}

/// Query for a single variant in the RocksDB database.
pub fn query_for_variant(
variant: &spdi::Var,
db: &rocksdb::DBWithThreadMode<rocksdb::MultiThreaded>,
out_writer: &mut dyn std::io::Write,
_out_format: common::cli::OutputFormat,
) -> Result<(), anyhow::Error> {
) -> Result<Option<Record>, anyhow::Error> {
let seq = variant.sequence.to_lowercase();
let var: keys::Var = variant.clone().into();
let key: Vec<u8> = var.into();
if seq.contains('m') {
let cf_mtdna: Arc<rocksdb::BoundColumnFamily> = db.cf_handle("mitochondrial").unwrap();
let raw_value = db.get_cf(&cf_mtdna, &key)?;
let raw_value = db
.get_cf(&cf_mtdna, &key)
.map_err(|e| anyhow::anyhow!("error reading from RocksDB: {}", e))?;
if let Some(raw_value) = raw_value {
let value = freqs::serialized::mt::Record::from_buf(&raw_value);
let json_value = serde_json::to_value(value)?;
let json = serde_json::to_string(&json_value)?;
writeln!(out_writer, "{}", &json)?;
return Ok(Some(Record::Mitochondrial(
freqs::serialized::mt::Record::from_buf(&raw_value),
)));
}
} else if seq.contains('x') || seq.contains('y') {
let cf_xy: Arc<rocksdb::BoundColumnFamily> = db.cf_handle("gonosomal").unwrap();
let raw_value = db.get_cf(&cf_xy, &key)?;
let raw_value = db
.get_cf(&cf_xy, &key)
.map_err(|e| anyhow::anyhow!("error reading from RocksDB: {}", e))?;
if let Some(raw_value) = raw_value {
let value = freqs::serialized::xy::Record::from_buf(&raw_value);
let json_value = serde_json::to_value(value)?;
let json = serde_json::to_string(&json_value)?;
writeln!(out_writer, "{}", &json)?;
return Ok(Some(Record::Gonosomal(
freqs::serialized::xy::Record::from_buf(&raw_value),
)));
}
} else {
let cf_auto: Arc<rocksdb::BoundColumnFamily> = db.cf_handle("autosomal").unwrap();
let raw_value = db.get_cf(&cf_auto, &key)?;
let raw_value = db
.get_cf(&cf_auto, &key)
.map_err(|e| anyhow::anyhow!("error reading from RocksDB: {}", e))?;
if let Some(raw_value) = raw_value {
let value = freqs::serialized::auto::Record::from_buf(&raw_value);
let json_value = serde_json::to_value(value)?;
let json = serde_json::to_string(&json_value)?;
writeln!(out_writer, "{}", &json)?;
return Ok(Some(Record::Autosomal(
freqs::serialized::auto::Record::from_buf(&raw_value),
)));
}
}

Ok(())
Ok(None)
}

/// Implementation of `tsv query` sub command.
Expand All @@ -146,7 +158,27 @@ pub fn run(common: &common::cli::Args, args: &Args) -> Result<(), anyhow::Error>

tracing::info!("Running query...");
let before_query = std::time::Instant::now();
query_for_variant(&args.variant, &db, &mut out_writer, args.out_format)?;
if let Some(variant) = query_for_variant(&args.variant, &db, args.out_format)? {
match variant {
Record::Autosomal(record) => {
let json_value = serde_json::to_value(record)?;
let json = serde_json::to_string(&json_value)?;
writeln!(out_writer, "{}", &json)?;
}
Record::Gonosomal(record) => {
let json_value = serde_json::to_value(record)?;
let json = serde_json::to_string(&json_value)?;
writeln!(out_writer, "{}", &json)?;
}
Record::Mitochondrial(record) => {
let json_value = serde_json::to_value(record)?;
let json = serde_json::to_string(&json_value)?;
writeln!(out_writer, "{}", &json)?;
}
}
} else {
tracing::info!("no record found for variant {:?}", &args.variant);
}
tracing::info!("... done querying in {:?}", before_query.elapsed());

tracing::info!("All done. Have a nice day!");
Expand Down
34 changes: 25 additions & 9 deletions src/genes/cli/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,28 @@ fn print_record(
Ok(())
}

/// Query for one gene annotation record.
pub fn query_for_gene(
hgnc_id: &str,
db: &rocksdb::DBWithThreadMode<rocksdb::MultiThreaded>,
cf_data: &Arc<rocksdb::BoundColumnFamily>,
) -> Result<Option<pbs::Record>, anyhow::Error> {
let raw_value = db
.get_cf(cf_data, hgnc_id.as_bytes())
.map_err(|e| anyhow::anyhow!("error while querying for HGNC ID {}: {}", hgnc_id, e))?;
raw_value
.map(|raw_value| {
pbs::Record::decode(&mut std::io::Cursor::new(&raw_value)).map_err(|e| {
anyhow::anyhow!(
"error while decoding gene record for HGNC ID {}: {}",
hgnc_id,
e
)
})
})
.transpose()
}

/// Implementation of `gene query` sub command.
pub fn run(common: &common::cli::Args, args: &Args) -> Result<(), anyhow::Error> {
tracing::info!("Starting 'gene query' command");
Expand All @@ -94,17 +116,11 @@ pub fn run(common: &common::cli::Args, args: &Args) -> Result<(), anyhow::Error>
};

tracing::info!("Running query...");
let raw_value = db.get_cf(&cf_data, args.hgnc_id.as_bytes())?;
if let Some(raw_value) = raw_value {
print_record(
&mut out_writer,
args.out_format,
&pbs::Record::decode(&mut std::io::Cursor::new(&raw_value))?,
)?;
if let Some(record) = query_for_gene(&args.hgnc_id, &db, &cf_data)? {
print_record(&mut out_writer, args.out_format, &record)?;
} else {
tracing::info!("No data found for HGNC ID {}", args.hgnc_id);
tracing::info!("no record found for HGNC ID {:?}", args.hgnc_id);
}

tracing::info!("All done. Have a nice day!");
Ok(())
}
26 changes: 15 additions & 11 deletions src/gnomad_mtdna/cli/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ pub fn query_for_variant(
meta: &Meta,
db: &rocksdb::DBWithThreadMode<rocksdb::MultiThreaded>,
cf_data: &Arc<rocksdb::BoundColumnFamily>,
) -> Result<gnomad_pbs::mtdna::Record, anyhow::Error> {
) -> Result<Option<gnomad_pbs::mtdna::Record>, anyhow::Error> {
// Split off the genome release (checked) and convert to key as used in database.
let query = spdi::Var {
sequence: extract_chrom::from_var(variant, Some(&meta.genome_release))?,
Expand All @@ -113,11 +113,15 @@ pub fn query_for_variant(
let var: keys::Var = query.into();
let key: Vec<u8> = var.into();
let raw_value = db
.get_cf(cf_data, key)?
.ok_or_else(|| anyhow::anyhow!("could not find variant in database"))?;
// Decode via prost.
gnomad_pbs::mtdna::Record::decode(&mut std::io::Cursor::new(&raw_value))
.map_err(|e| anyhow::anyhow!("failed to decode record: {}", e))
.get_cf(cf_data, key)
.map_err(|e| anyhow::anyhow!("error reading from RocksDB: {}", e))?;
raw_value
.map(|raw_value| {
// Decode via prost.
gnomad_pbs::mtdna::Record::decode(&mut std::io::Cursor::new(&raw_value))
.map_err(|e| anyhow::anyhow!("failed to decode record: {}", e))
})
.transpose()
}

/// Implementation of `tsv query` sub command.
Expand All @@ -141,11 +145,11 @@ pub fn run(common: &common::cli::Args, args: &Args) -> Result<(), anyhow::Error>
tracing::info!("Running query...");
let before_query = std::time::Instant::now();
if let Some(variant) = args.query.variant.as_ref() {
print_record(
&mut out_writer,
args.out_format,
&query_for_variant(variant, &meta, &db, &cf_data)?,
)?;
if let Some(record) = query_for_variant(variant, &meta, &db, &cf_data)? {
print_record(&mut out_writer, args.out_format, &record)?;
} else {
tracing::info!("no record found for variant {:?}", &variant);
}
} else {
let (start, stop) = if let Some(position) = args.query.position.as_ref() {
let position = spdi::Pos {
Expand Down
26 changes: 15 additions & 11 deletions src/gnomad_nuclear/cli/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ pub fn query_for_variant(
meta: &Meta,
db: &rocksdb::DBWithThreadMode<rocksdb::MultiThreaded>,
cf_data: &Arc<rocksdb::BoundColumnFamily>,
) -> Result<gnomad_pbs::gnomad2::Record, anyhow::Error> {
) -> Result<Option<gnomad_pbs::gnomad2::Record>, anyhow::Error> {
// Split off the genome release (checked) and convert to key as used in database.
let query = spdi::Var {
sequence: extract_chrom::from_var(variant, Some(&meta.genome_release))?,
Expand All @@ -113,11 +113,15 @@ pub fn query_for_variant(
let var: keys::Var = query.into();
let key: Vec<u8> = var.into();
let raw_value = db
.get_cf(cf_data, key)?
.ok_or_else(|| anyhow::anyhow!("could not find variant in database"))?;
// Decode via prost.
gnomad_pbs::gnomad2::Record::decode(&mut std::io::Cursor::new(&raw_value))
.map_err(|e| anyhow::anyhow!("failed to decode record: {}", e))
.get_cf(cf_data, key)
.map_err(|e| anyhow::anyhow!("problem querying RocksDB: {}", e))?;
raw_value
.map(|raw_value| {
// Decode via prost.
gnomad_pbs::gnomad2::Record::decode(&mut std::io::Cursor::new(&raw_value))
.map_err(|e| anyhow::anyhow!("failed to decode record: {}", e))
})
.transpose()
}

/// Implementation of `tsv query` sub command.
Expand All @@ -141,11 +145,11 @@ pub fn run(common: &common::cli::Args, args: &Args) -> Result<(), anyhow::Error>
tracing::info!("Running query...");
let before_query = std::time::Instant::now();
if let Some(variant) = args.query.variant.as_ref() {
print_record(
&mut out_writer,
args.out_format,
&query_for_variant(variant, &meta, &db, &cf_data)?,
)?;
if let Some(record) = query_for_variant(variant, &meta, &db, &cf_data)? {
print_record(&mut out_writer, args.out_format, &record)?
} else {
tracing::info!("no record found for variant {:?}", &variant);
}
} else {
let (start, stop) = if let Some(position) = args.query.position.as_ref() {
let position = spdi::Pos {
Expand Down
Loading

0 comments on commit b4bf349

Please sign in to comment.