Skip to content

Commit 65af00d

Browse files
fix(frontend): bind background exec to caller session (#26023)
## What type of PR is this? - [ ] API-change - [ ] BUG - [ ] Improvement - [ ] Documentation - [ ] Feature - [ ] Test and CI - [ ] Code Refactoring ## Which issue(s) this PR fixes: issue #25414 ## What this PR does / why we need it: fix(frontend): bind background exec to caller session Co-authored-by: XuPeng-SH <xupeng3112@163.com>
1 parent d4c70a0 commit 65af00d

4 files changed

Lines changed: 135 additions & 0 deletions

File tree

pkg/frontend/back_exec.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ func doComQueryInBack(
397397
Buf: backSes.buf,
398398
}
399399
proc.SetAffectedRows(backSes.lastAffectedRows)
400+
bindBackExecSession(proc, backSes)
400401
proc.SetStmtProfile(&backSes.stmtProfile)
401402
proc.SetResolveVariableFunc(backSes.txnCompileCtx.ResolveVariable)
402403
proc.SetResolveVariableIsBinFunc(backSes.txnCompileCtx.ResolveVariableIsBin)
@@ -580,6 +581,18 @@ func affectedRowsForStatement(execCtx *ExecCtx) int64 {
580581
return 0
581582
}
582583

584+
// bindBackExecSession preserves the caller's session scope for SQL executed by
585+
// a frontend background executor. The back session forwards temporary-table
586+
// aliases to its upstream session, while the upstream ID keeps physical table
587+
// names visible to the temporary-table GC as belonging to the active client.
588+
func bindBackExecSession(proc *process.Process, backSes *backSession) {
589+
if backSes.upstream == nil {
590+
return
591+
}
592+
proc.Session = backSes
593+
proc.Base.SessionInfo.SessionId = backSes.upstream.GetSessId()
594+
}
595+
583596
func executeStmtInBack(backSes *backSession,
584597
statsArr *statistic.StatsArray,
585598
execCtx *ExecCtx,
@@ -1028,6 +1041,7 @@ func (backSes *backSession) InitBackExec(txnOp TxnOperator, db string, callBack
10281041
if txnOp != nil {
10291042
be := &backExec{}
10301043
be.init(backSes, txnOp, db, callBack)
1044+
be.backSes.upstream = backSes.upstream
10311045
return be
10321046
} else if backSes.upstream != nil {
10331047
// XXXSP

pkg/frontend/back_exec_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright 2026 Matrix Origin
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package frontend
16+
17+
import (
18+
"testing"
19+
20+
"github.com/google/uuid"
21+
"github.com/stretchr/testify/require"
22+
23+
"github.com/matrixorigin/matrixone/pkg/vm/process"
24+
)
25+
26+
func TestBindBackExecSession(t *testing.T) {
27+
clientSessionID := uuid.New()
28+
backSessionID := uuid.New()
29+
clientSession := &Session{
30+
feSessionImpl: feSessionImpl{uuid: clientSessionID},
31+
tempTables: make(map[string]string),
32+
tempTablesRev: make(map[string]string),
33+
}
34+
backSes := &backSession{
35+
feSessionImpl: feSessionImpl{
36+
uuid: backSessionID,
37+
upstream: clientSession,
38+
},
39+
}
40+
proc := &process.Process{Base: &process.BaseProcess{}}
41+
42+
bindBackExecSession(proc, backSes)
43+
44+
require.Same(t, backSes, proc.GetSession())
45+
require.Equal(t, clientSessionID, proc.Base.SessionInfo.SessionId)
46+
proc.GetSession().AddTempTable("db1", "tmp1", "real_tmp1")
47+
realName, ok := clientSession.GetTempTable("db1", "tmp1")
48+
require.True(t, ok)
49+
require.Equal(t, "real_tmp1", realName)
50+
}
51+
52+
func TestBindBackExecSessionWithoutUpstream(t *testing.T) {
53+
backSessionID := uuid.New()
54+
backSes := &backSession{
55+
feSessionImpl: feSessionImpl{uuid: backSessionID},
56+
}
57+
proc := &process.Process{Base: &process.BaseProcess{}}
58+
59+
bindBackExecSession(proc, backSes)
60+
61+
require.Nil(t, proc.GetSession())
62+
require.Equal(t, uuid.Nil, proc.Base.SessionInfo.SessionId)
63+
}

test/distributed/cases/procedure/procedure.result

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,33 @@ select @id;
9595
1000
9696
drop procedure test_inout_param;
9797

98+
drop procedure if exists test_temp_table_lifecycle;
99+
create procedure test_temp_table_lifecycle() 'begin create temporary table tmp_proc_lifecycle (id int primary key, v int); insert into tmp_proc_lifecycle select id, val from tbh1 where id <= 2; select sum(v) as tmp_sum from tmp_proc_lifecycle; drop table tmp_proc_lifecycle; end';
100+
call test_temp_table_lifecycle();
101+
tmp_sum
102+
30
103+
drop procedure test_temp_table_lifecycle;
104+
drop procedure if exists test_temp_table_session_binding;
105+
create procedure test_temp_table_session_binding() 'begin create temporary table tmp_proc_session (id int primary key, v int); insert into tmp_proc_session select id, val from tbh1 where id <= 2; end';
106+
call test_temp_table_session_binding();
107+
select sum(v) as tmp_sum from tmp_proc_session;
108+
tmp_sum
109+
30
110+
drop table tmp_proc_session;
111+
drop procedure test_temp_table_session_binding;
112+
113+
drop procedure if exists test_nested_temp_table_outer;
114+
drop procedure if exists test_nested_temp_table_inner;
115+
create procedure test_nested_temp_table_inner() 'begin create temporary table tmp_nested_proc_session (id int primary key, v int); insert into tmp_nested_proc_session select id, val from tbh1 where id <= 2; end';
116+
create procedure test_nested_temp_table_outer() 'begin call test_nested_temp_table_inner(); end';
117+
call test_nested_temp_table_outer();
118+
select sum(v) as tmp_sum from tmp_nested_proc_session;
119+
tmp_sum
120+
30
121+
drop table tmp_nested_proc_session;
122+
drop procedure test_nested_temp_table_outer;
123+
drop procedure test_nested_temp_table_inner;
124+
98125
set sql_mode = 'PIPES_AS_CONCAT';
99126
create procedure test_sql_mode_pipes() 'begin select ''a''||''b'' as c; end';
100127
set sql_mode = '';

test/distributed/cases/procedure/procedure.sql

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,37 @@ call test_inout_param(@id);
110110
select @id;
111111
drop procedure test_inout_param;
112112

113+
-- @case
114+
-- @desc:temporary table lifecycle inside a stored procedure
115+
-- @label:bvt
116+
drop procedure if exists test_temp_table_lifecycle;
117+
create procedure test_temp_table_lifecycle() 'begin create temporary table tmp_proc_lifecycle (id int primary key, v int); insert into tmp_proc_lifecycle select id, val from tbh1 where id <= 2; select sum(v) as tmp_sum from tmp_proc_lifecycle; drop table tmp_proc_lifecycle; end';
118+
call test_temp_table_lifecycle();
119+
drop procedure test_temp_table_lifecycle;
120+
121+
-- @case
122+
-- @desc:temporary table created in a stored procedure remains bound to the caller session
123+
-- @label:bvt
124+
drop procedure if exists test_temp_table_session_binding;
125+
create procedure test_temp_table_session_binding() 'begin create temporary table tmp_proc_session (id int primary key, v int); insert into tmp_proc_session select id, val from tbh1 where id <= 2; end';
126+
call test_temp_table_session_binding();
127+
select sum(v) as tmp_sum from tmp_proc_session;
128+
drop table tmp_proc_session;
129+
drop procedure test_temp_table_session_binding;
130+
131+
-- @case
132+
-- @desc:temporary table created in a nested stored procedure remains bound to the caller session
133+
-- @label:bvt
134+
drop procedure if exists test_nested_temp_table_outer;
135+
drop procedure if exists test_nested_temp_table_inner;
136+
create procedure test_nested_temp_table_inner() 'begin create temporary table tmp_nested_proc_session (id int primary key, v int); insert into tmp_nested_proc_session select id, val from tbh1 where id <= 2; end';
137+
create procedure test_nested_temp_table_outer() 'begin call test_nested_temp_table_inner(); end';
138+
call test_nested_temp_table_outer();
139+
select sum(v) as tmp_sum from tmp_nested_proc_session;
140+
drop table tmp_nested_proc_session;
141+
drop procedure test_nested_temp_table_outer;
142+
drop procedure test_nested_temp_table_inner;
143+
113144
-- @case
114145
-- @desc:procedure parser SQL mode is retained after caller mode changes
115146
-- @label:bvt

0 commit comments

Comments
 (0)