use crate::types::PropertyValue;
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub enum NqlResult {
Query(QueryResult),
Write(WriteResult),
Index(String),
Explain(String),
Profile(ProfileResult),
Export { format: String, data: String, rows_exported: usize },
Message(String),
}
impl NqlResult {
pub fn into_query(self) -> crate::error::Result<QueryResult> {
match self {
NqlResult::Query(r) => Ok(r),
other => Err(crate::error::NopalError::QueryExecutionError(
format!("Expected Query result, got {:?}", std::mem::discriminant(&other))
)),
}
}
pub fn summary(&self) -> String {
match self {
NqlResult::Query(r) => format!("{} rows returned", r.len()),
NqlResult::Write(w) => format!(
"{} nodes created, {} edges created, {} nodes deleted, {} edges deleted, {} nodes updated, {} edges updated",
w.nodes_created, w.edges_created, w.nodes_deleted, w.edges_deleted, w.nodes_updated, w.edges_updated
),
NqlResult::Index(msg) => msg.clone(),
NqlResult::Explain(plan) => plan.clone(),
NqlResult::Profile(profile) => format!(
"PROFILE query: {} rows, {:.3} ms",
profile.rows_returned, profile.execution_ms
),
NqlResult::Export { format, rows_exported, .. } => {
format!("Exported {} rows as {}", rows_exported, format)
}
NqlResult::Message(msg) => msg.clone(),
}
}
}
#[derive(Debug, Clone)]
pub struct WriteResult {
pub nodes_created: usize,
pub edges_created: usize,
pub nodes_deleted: usize,
pub edges_deleted: usize,
pub nodes_updated: usize,
pub edges_updated: usize,
pub properties_changed: usize,
pub created_ids: Vec<String>,
}
impl WriteResult {
pub fn from_add(add: &AddResult) -> Self {
WriteResult {
nodes_created: add.nodes_created,
edges_created: add.edges_created,
nodes_deleted: 0,
edges_deleted: 0,
nodes_updated: 0,
edges_updated: 0,
properties_changed: 0,
created_ids: add.created_ids.clone(),
}
}
pub fn from_delete(del: &DeleteResult) -> Self {
WriteResult {
nodes_created: 0,
edges_created: 0,
nodes_deleted: del.nodes_deleted,
edges_deleted: del.edges_deleted,
nodes_updated: 0,
edges_updated: 0,
properties_changed: 0,
created_ids: Vec::new(),
}
}
pub fn from_update(upd: &UpdateResult) -> Self {
WriteResult {
nodes_created: 0,
edges_created: 0,
nodes_deleted: 0,
edges_deleted: 0,
nodes_updated: upd.nodes_updated,
edges_updated: upd.edges_updated,
properties_changed: upd.properties_changed,
created_ids: Vec::new(),
}
}
}
#[derive(Debug, Clone)]
pub struct QueryResult {
pub columns: Vec<String>,
pub rows: Vec<Row>,
}
#[derive(Debug, Clone)]
pub struct ProfileResult {
pub plan: String,
pub statement_type: String,
pub execution_ms: f64,
pub rows_returned: i64,
pub columns: Vec<String>,
pub path_query: bool,
pub path_metrics: Option<PropertyValue>,
}
#[derive(Debug, Clone)]
pub struct AddResult {
pub nodes_created: usize,
pub edges_created: usize,
pub created_ids: Vec<String>,
}
impl AddResult {
pub fn new() -> Self {
AddResult {
nodes_created: 0,
edges_created: 0,
created_ids: Vec::new(),
}
}
}
impl Default for AddResult {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct DeleteResult {
pub nodes_deleted: usize,
pub edges_deleted: usize,
}
impl DeleteResult {
pub fn new() -> Self {
DeleteResult {
nodes_deleted: 0,
edges_deleted: 0,
}
}
}
impl Default for DeleteResult {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct UpdateResult {
pub nodes_updated: usize,
pub edges_updated: usize,
pub properties_changed: usize,
}
impl UpdateResult {
pub fn new() -> Self {
UpdateResult {
nodes_updated: 0,
edges_updated: 0,
properties_changed: 0,
}
}
}
impl Default for UpdateResult {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct Row {
pub values: HashMap<String, PropertyValue>,
}
impl QueryResult {
pub fn empty() -> Self {
QueryResult {
columns: vec![],
rows: vec![],
}
}
pub fn new(columns: Vec<String>) -> Self {
QueryResult {
columns,
rows: vec![],
}
}
pub fn add_row(&mut self, row: Row) {
self.rows.push(row);
}
pub fn rows(&self) -> &[Row] {
&self.rows
}
pub fn len(&self) -> usize {
self.rows.len()
}
pub fn is_empty(&self) -> bool {
self.rows.is_empty()
}
pub fn to_csv(&self) -> String {
super::export::query_result_to_csv(self, ",", true)
}
pub fn to_csv_custom(&self, separator: &str, include_header: bool) -> String {
super::export::query_result_to_csv(self, separator, include_header)
}
pub fn to_json(&self) -> String {
super::export::query_result_to_json(self, false)
}
pub fn to_json_pretty(&self) -> String {
super::export::query_result_to_json(self, true)
}
}
impl Row {
pub fn new() -> Self {
Row {
values: HashMap::new(),
}
}
pub fn set(&mut self, key: impl Into<String>, value: PropertyValue) {
self.values.insert(key.into(), value);
}
pub fn get(&self, key: &str) -> Option<&PropertyValue> {
self.values.get(key)
}
pub fn get_string(&self, key: &str) -> Option<String> {
match self.get(key)? {
PropertyValue::String(s) => Some(s.clone()),
_ => None,
}
}
pub fn get_int(&self, key: &str) -> Option<i64> {
match self.get(key)? {
PropertyValue::Int(i) => Some(*i),
_ => None,
}
}
pub fn keys(&self) -> Vec<&String> {
self.values.keys().collect()
}
}
impl Default for Row {
fn default() -> Self {
Self::new()
}
}
impl std::ops::Index<&str> for Row {
type Output = PropertyValue;
fn index(&self, key: &str) -> &Self::Output {
static NULL: PropertyValue = PropertyValue::Null;
self.values.get(key).unwrap_or(&NULL)
}
}