From 9eb81c0a465959e2da2e5c1d53ef4c8089201966 Mon Sep 17 00:00:00 2001 From: James Cor Date: Thu, 1 May 2025 14:34:04 -0700 Subject: [PATCH 1/2] fix recursive procedures --- enginetest/queries/procedure_queries.go | 46 +++++++++++++++++++++++++ sql/core.go | 2 +- sql/rowexec/proc.go | 3 ++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/enginetest/queries/procedure_queries.go b/enginetest/queries/procedure_queries.go index 7ca990a260..f9cc7fc6e3 100644 --- a/enginetest/queries/procedure_queries.go +++ b/enginetest/queries/procedure_queries.go @@ -2192,6 +2192,52 @@ END;`, }, }, }, + { + Name: "recursive procedure", + SetUpScript: []string{ + ` +create procedure recursive_proc(in counter int) +begin + set counter := counter + 1; + if counter > 3 then + select concat('ended with value: ', counter) as result; + else + call recursive_proc(counter); + end if; +end;`, + }, + Assertions: []ScriptTestAssertion{ + { + Query: "call recursive_proc(1);", + Expected: []sql.Row{ + {"ended with value: 4"}, + }, + }, + }, + }, + { + Name: "multi recursive procedures", + SetUpScript: []string{ + ` +create procedure recursive_proc(in counter int) +begin + set counter := counter + 1; + if counter > 3 then + select concat('ended with value: ', counter) as result; + else + call recursive_proc(counter); + end if; +end;`, + }, + Assertions: []ScriptTestAssertion{ + { + Query: "call recursive_proc(1);", + Expected: []sql.Row{ + {"ended with value: 4"}, + }, + }, + }, + }, } var ProcedureCallTests = []ScriptTest{ diff --git a/sql/core.go b/sql/core.go index 3318835884..e2e7d0152d 100644 --- a/sql/core.go +++ b/sql/core.go @@ -894,7 +894,7 @@ type StoredProcParam struct { func (s *StoredProcParam) SetValue(val any) { s.Value = val s.HasBeenSet = true - if s.Reference != nil { + if s.Reference != nil && s != s.Reference { s.Reference.SetValue(val) } } diff --git a/sql/rowexec/proc.go b/sql/rowexec/proc.go index f456354862..35af6c65e8 100644 --- a/sql/rowexec/proc.go +++ b/sql/rowexec/proc.go @@ -223,6 +223,9 @@ func (b *BaseBuilder) buildCall(ctx *sql.Context, n *plan.Call, row sql.Row) (sq paramName := strings.ToLower(param.Name) for spp := ctx.Session.GetStoredProcParam(paramName); spp != nil; { spp.Value = paramVal + if spp.Reference == spp { + break + } spp = spp.Reference } } From affaa51f26a3a04e951c75f83e4155be18853858 Mon Sep 17 00:00:00 2001 From: James Cor Date: Thu, 1 May 2025 14:44:45 -0700 Subject: [PATCH 2/2] more tests --- enginetest/queries/procedure_queries.go | 30 ++++++++++++++++++++----- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/enginetest/queries/procedure_queries.go b/enginetest/queries/procedure_queries.go index f9cc7fc6e3..9fb9cc4f81 100644 --- a/enginetest/queries/procedure_queries.go +++ b/enginetest/queries/procedure_queries.go @@ -2219,21 +2219,39 @@ end;`, Name: "multi recursive procedures", SetUpScript: []string{ ` -create procedure recursive_proc(in counter int) +create procedure procA(in counter int) begin set counter := counter + 1; if counter > 3 then - select concat('ended with value: ', counter) as result; + select concat('ended in procA with value: ', counter) as result; else - call recursive_proc(counter); + call procB(counter); end if; -end;`, +end; +`, + ` +create procedure procB(in counter int) +begin + set counter := counter + 1; + if counter > 3 then + select concat('ended in procB with value: ', counter) as result; + else + call procA(counter); + end if; +end; +`, }, Assertions: []ScriptTestAssertion{ { - Query: "call recursive_proc(1);", + Query: "call procA(1);", Expected: []sql.Row{ - {"ended with value: 4"}, + {"ended in procA with value: 4"}, + }, + }, + { + Query: "call procB(1);", + Expected: []sql.Row{ + {"ended in procB with value: 4"}, }, }, },