From bbcb04cc15a8fd3dde612f458952a7a9b2eaeb9a Mon Sep 17 00:00:00 2001
From: Arseniy Volynets <a.volynets@picodata.io>
Date: Mon, 23 Sep 2024 12:09:32 +0300
Subject: [PATCH] feat: handle no values for params case correctly

---
 .../test_app/test/integration/api_test.lua    |  4 +--
 sbroad-core/src/ir/api/parameter.rs           | 30 +++++++++++++++++--
 2 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/sbroad-cartridge/test_app/test/integration/api_test.lua b/sbroad-cartridge/test_app/test/integration/api_test.lua
index cf60d18a39..5985e48780 100644
--- a/sbroad-cartridge/test_app/test/integration/api_test.lua
+++ b/sbroad-cartridge/test_app/test/integration/api_test.lua
@@ -213,9 +213,9 @@ g.test_query_errored = function()
 
     -- check err when params lenght is less then amount of sign `?`
     local _, err = api:call("sbroad.execute", { [[SELECT * FROM "testing_space" where "id" = ?]], {} })
-    t.assert_equals(
+    t.assert_str_contains(
         tostring(err),
-        "Sbroad Error: build query: invalid node: parameter node does not refer to an expression"
+        "Expected at least 1 values for parameters. Got 0"
     )
 end
 
diff --git a/sbroad-core/src/ir/api/parameter.rs b/sbroad-core/src/ir/api/parameter.rs
index 7fe94423bb..eb6597ecc8 100644
--- a/sbroad-core/src/ir/api/parameter.rs
+++ b/sbroad-core/src/ir/api/parameter.rs
@@ -1,4 +1,4 @@
-use crate::errors::SbroadError;
+use crate::errors::{Entity, SbroadError};
 use crate::ir::node::block::{Block, MutBlock};
 use crate::ir::node::expression::{Expression, MutExpression};
 use crate::ir::node::relational::{MutRelational, Relational};
@@ -7,7 +7,7 @@ use crate::ir::node::{
     MutNode, Node64, NodeId, Parameter, Procedure, Row, Selection, StableFunction, Trim, UnaryExpr,
     ValuesRow,
 };
-use crate::ir::tree::traversal::{LevelNode, PostOrder};
+use crate::ir::tree::traversal::{LevelNode, PostOrder, PostOrderWithFilter};
 use crate::ir::value::Value;
 use crate::ir::{ArenaType, Node, OptionParamValue, Plan, ValueIdx};
 use crate::otm::child_span;
@@ -687,8 +687,32 @@ impl Plan {
     #[allow(clippy::too_many_lines)]
     #[otm_child_span("plan.bind")]
     pub fn bind_params(&mut self, values: Vec<Value>) -> Result<(), SbroadError> {
-        // Nothing to do here.
         if values.is_empty() {
+            // Check there are no parameters in the plan,
+            // we must fail early here, rather than on
+            // later pipeline stages.
+            let mut param_count: usize = 0;
+            let filter = Box::new(|x: NodeId| -> bool {
+                if let Ok(Node::Parameter(_)) = self.get_node(x) {
+                    param_count += 1;
+                }
+                false
+            });
+            let mut dfs =
+                PostOrderWithFilter::with_capacity(|x| self.subtree_iter(x, false), 0, filter);
+            dfs.populate_nodes(self.get_top()?);
+            drop(dfs);
+
+            if param_count > 0 {
+                return Err(SbroadError::Invalid(
+                    Entity::Query,
+                    Some(format_smolstr!(
+                        "Expected at least {param_count} values for parameters. Got 0"
+                    )),
+                ));
+            }
+
+            // Nothing to do here.
             return Ok(());
         }
 
-- 
GitLab