From 2219388802dd9d769e17c15f6f3d94bb2cd64676 Mon Sep 17 00:00:00 2001 From: Tobie Morgan Hitchcock Date: Thu, 16 May 2024 16:51:09 +0100 Subject: [PATCH] Prevent subqueries from being executed multiple times (#4051) --- core/src/sql/data.rs | 27 +++++++++++++----------- lib/tests/create.rs | 50 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 12 deletions(-) diff --git a/core/src/sql/data.rs b/core/src/sql/data.rs index 73230efb..74e848c3 100644 --- a/core/src/sql/data.rs +++ b/core/src/sql/data.rs @@ -43,18 +43,21 @@ impl Data { txn: &Transaction, ) -> Result, Error> { match self { - Self::MergeExpression(v) => { - // This MERGE expression has an 'id' field - Ok(v.compute(stk, ctx, opt, txn, None).await?.rid().some()) - } - Self::ReplaceExpression(v) => { - // This REPLACE expression has an 'id' field - Ok(v.compute(stk, ctx, opt, txn, None).await?.rid().some()) - } - Self::ContentExpression(v) => { - // This CONTENT expression has an 'id' field - Ok(v.compute(stk, ctx, opt, txn, None).await?.rid().some()) - } + Self::MergeExpression(v) => match v { + Value::Param(v) => Ok(v.compute(stk, ctx, opt, txn, None).await?.rid().some()), + Value::Object(_) => Ok(v.rid().some()), + _ => Ok(None), + }, + Self::ReplaceExpression(v) => match v { + Value::Param(v) => Ok(v.compute(stk, ctx, opt, txn, None).await?.rid().some()), + Value::Object(_) => Ok(v.rid().some()), + _ => Ok(None), + }, + Self::ContentExpression(v) => match v { + Value::Param(v) => Ok(v.compute(stk, ctx, opt, txn, None).await?.rid().some()), + Value::Object(_) => Ok(v.rid().some()), + _ => Ok(None), + }, Self::SetExpression(v) => match v.iter().find(|f| f.0.is_id()) { Some((_, _, v)) => { // This SET expression has an 'id' field diff --git a/lib/tests/create.rs b/lib/tests/create.rs index c9ece08d..c0c03bca 100644 --- a/lib/tests/create.rs +++ b/lib/tests/create.rs @@ -397,6 +397,56 @@ async fn create_with_unique_index_on_two_fields() -> Result<(), Error> { Ok(()) } +#[tokio::test] +async fn create_with_subquery_execution() -> Result<(), Error> { + let sql = " + CREATE person:test CONTENT { + address: (CREATE ONLY address CONTENT { + id: 'test', city: 'London' + }) + }; + SELECT * FROM person, address; + "; + let dbs = new_ds().await?; + let ses = Session::owner().with_ns("test").with_db("test"); + let res = &mut dbs.execute(sql, &ses, None).await?; + assert_eq!(res.len(), 2); + // + let tmp = res.remove(0).result?; + let val = Value::parse( + "[ + { + address: { + city: 'London', + id: address:test + }, + id: person:test + } + ]", + ); + assert_eq!(tmp, val); + // + let tmp = res.remove(0).result?; + let val = Value::parse( + "[ + { + address: { + city: 'London', + id: address:test + }, + id: person:test + }, + { + city: 'London', + id: address:test + } + ]", + ); + assert_eq!(tmp, val); + // + Ok(()) +} + // // Permissions //