From 4d9b3fd40399a9b0016f9e8935961171f80b4b84 Mon Sep 17 00:00:00 2001 From: Tobie Morgan Hitchcock Date: Tue, 31 May 2022 20:44:27 +0100 Subject: [PATCH] Ensure fields are not escaped when inserted as object keys --- lib/src/sql/ident.rs | 6 ++++++ lib/src/sql/idiom.rs | 15 +++++++++++++++ lib/src/sql/object.rs | 2 +- lib/src/sql/value/set.rs | 2 +- lib/src/sql/value/value.rs | 33 ++++++++++++++++++++++++++------- 5 files changed, 49 insertions(+), 9 deletions(-) diff --git a/lib/src/sql/ident.rs b/lib/src/sql/ident.rs index f8df5019..380ad3ad 100644 --- a/lib/src/sql/ident.rs +++ b/lib/src/sql/ident.rs @@ -43,6 +43,12 @@ impl Deref for Ident { } } +impl Ident { + pub fn to_raw(&self) -> String { + self.0.to_string() + } +} + impl fmt::Display for Ident { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", escape_ident(&self.0)) diff --git a/lib/src/sql/idiom.rs b/lib/src/sql/idiom.rs index 8c180feb..d77b9334 100644 --- a/lib/src/sql/idiom.rs +++ b/lib/src/sql/idiom.rs @@ -45,6 +45,12 @@ impl Deref for Idiom { } } +impl From for Idiom { + fn from(v: String) -> Self { + Idiom(vec![Part::from(v)]) + } +} + impl From> for Idiom { fn from(v: Vec) -> Self { Idiom(v) @@ -61,6 +67,15 @@ impl Idiom { pub fn to_path(&self) -> String { format!("/{}", self).replace(']', "").replace(&['.', '['][..], "/") } + /// + pub fn simplify(&self) -> Idiom { + self.0 + .iter() + .cloned() + .filter(|p| matches!(p, Part::Field(_) | Part::Graph(_))) + .collect::>() + .into() + } } impl Idiom { diff --git a/lib/src/sql/object.rs b/lib/src/sql/object.rs index 6efa90fb..1fcc6fb7 100644 --- a/lib/src/sql/object.rs +++ b/lib/src/sql/object.rs @@ -91,7 +91,7 @@ impl Object { Some(o) => match self.get("path") { Some(p) => Ok(Operation { op: o.into(), - path: p.to_idiom(), + path: p.jsonpath(), value: match self.get("value") { Some(v) => v.clone(), None => Value::Null, diff --git a/lib/src/sql/value/set.rs b/lib/src/sql/value/set.rs index ff0c3953..2a98547f 100644 --- a/lib/src/sql/value/set.rs +++ b/lib/src/sql/value/set.rs @@ -29,7 +29,7 @@ impl Value { _ => { let mut obj = Value::base(); obj.set(ctx, opt, txn, path.next(), val).await?; - v.insert(f.to_string(), obj); + v.insert(f.to_raw(), obj); Ok(()) } }, diff --git a/lib/src/sql/value/value.rs b/lib/src/sql/value/value.rs index 08f9ae75..a6bbb87b 100644 --- a/lib/src/sql/value/value.rs +++ b/lib/src/sql/value/value.rs @@ -639,13 +639,18 @@ impl Value { } pub fn to_idiom(&self) -> Idiom { - self.to_strand() - .as_str() - .trim_start_matches('/') - .split(&['.', '/'][..]) - .map(Part::from) - .collect::>() - .into() + match self { + Value::Idiom(v) => v.simplify(), + Value::Strand(v) => v.0.to_string().into(), + Value::Datetime(v) => v.0.to_string().into(), + Value::Function(v) => match v.as_ref() { + Function::Future(_) => "fn::future".to_string().into(), + Function::Script(_) => "fn::script".to_string().into(), + Function::Normal(f, _) => f.to_string().into(), + _ => v.to_string().into(), + }, + _ => self.to_string().into(), + } } // ----------------------------------- @@ -738,6 +743,20 @@ impl Value { } } + // ----------------------------------- + // JSON Path conversion + // ----------------------------------- + + pub fn jsonpath(&self) -> Idiom { + self.to_strand() + .as_str() + .trim_start_matches('/') + .split(&['.', '/'][..]) + .map(Part::from) + .collect::>() + .into() + } + // ----------------------------------- // Value operations // -----------------------------------