This is an automated email from the ASF dual-hosted git repository.
924060929 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 954e717b1bf [fix](audit) record per-query SET_VAR hint session
variables in audit log (#64569)
954e717b1bf is described below
commit 954e717b1bfc053bac7dcd2d68625ca2fe269451
Author: 924060929 <[email protected]>
AuthorDate: Wed Jun 17 11:54:04 2026 +0800
[fix](audit) record per-query SET_VAR hint session variables in audit log
(#64569)
Problem Summary:
Session variables changed by a per-query `SET_VAR` hint (e.g.
`SELECT /*+ SET_VAR(session_context="trace_id:xxx") */ ...`) are
temporary: they are
reverted in the `finally` block of `StmtExecutor.execute()`. The audit
log is built
afterwards in `ConnectProcessor.auditAfterExec()`, which calls
`VariableMgr.dumpChangedVars()`
on the already-reverted session variables. As a result, the audit log
`changed_variables`
column never reflects variables set by a per-query `SET_VAR` hint — such
a variable always
shows up as missing there, while the same variable set at session level
via `SET ...` is
recorded correctly.
This PR snapshots the changed session variables in
`StmtExecutor.execute()` right before the
revert (only when a `SET_VAR` hint was used), and makes `AuditLogHelper`
prefer that snapshot,
so the audit log reflects the variables that were actually in effect for
the statement.
### Release note
Fix audit log `changed_variables` not recording session variables set by
a per-query `SET_VAR` hint.
---
.../java/org/apache/doris/qe/AuditLogHelper.java | 8 ++-
.../java/org/apache/doris/qe/StmtExecutor.java | 19 ++++++
.../test_audit_log_hint_session_context.groovy | 71 ++++++++++++++++++++++
3 files changed, 97 insertions(+), 1 deletion(-)
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/AuditLogHelper.java
b/fe/fe-core/src/main/java/org/apache/doris/qe/AuditLogHelper.java
index ccb4d0d14e8..fddc42ecd60 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/AuditLogHelper.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/AuditLogHelper.java
@@ -304,7 +304,13 @@ public class AuditLogHelper {
auditEventBuilder.setScheduleTimeMs(summaryProfile.getScheduleTime());
// changed variables
if (ctx.sessionVariable != null) {
- List<List<String>> changedVars =
VariableMgr.dumpChangedVars(ctx.sessionVariable);
+ // Prefer the pre-revert snapshot captured in StmtExecutor so
that per-query
+ // SET_VAR hint values are visible; fall back to the live
session variables when
+ // no snapshot was taken (i.e. the statement used no SET_VAR
hint).
+ List<List<String>> changedVars = (ctx.getExecutor() != null
+ && ctx.getExecutor().getChangedSessionVarsForAudit()
!= null)
+ ? ctx.getExecutor().getChangedSessionVarsForAudit()
+ : VariableMgr.dumpChangedVars(ctx.sessionVariable);
StringBuilder changedVarsStr = new StringBuilder();
changedVarsStr.append("{");
for (int i = 0; i < changedVars.size(); i++) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
index 3bcd045485f..eaa38e69f03 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
@@ -189,6 +189,10 @@ public class StmtExecutor {
private MysqlSerializer serializer;
private OriginStatement originStmt;
private StatementBase parsedStmt;
+ // Snapshot of changed session variables taken BEFORE per-query SET_VAR
hint values are
+ // reverted, so the audit log (built after execute() returns) can reflect
the values that
+ // were actually in effect for this statement. Null when no SET_VAR hint
was used.
+ private List<List<String>> changedSessionVarsForAudit;
private ProfileType profileType = ProfileType.QUERY;
@Setter
@@ -551,6 +555,10 @@ public class StmtExecutor {
return parsedStmt;
}
+ public List<List<String>> getChangedSessionVarsForAudit() {
+ return changedSessionVarsForAudit;
+ }
+
/**
* Replace the executor statement context and synchronize it to the owning
ConnectContext.
*/
@@ -650,6 +658,17 @@ public class StmtExecutor {
throw e;
}
} finally {
+ // Snapshot changed session variables (including SET_VAR hint
values) BEFORE revert,
+ // so the audit log (logged after execute() returns, i.e. after
the revert below) can
+ // reflect what was actually in effect for this statement instead
of the reverted values.
+ if (sessionVariable.getIsSingleSetVar()) {
+ try {
+ changedSessionVarsForAudit =
VariableMgr.dumpChangedVars(sessionVariable);
+ } catch (Throwable t) {
+ LOG.warn("failed to snapshot changed session variables for
audit. {}",
+ context.getQueryIdentifier(), t);
+ }
+ }
// revert Session Value
try {
VariableMgr.revertSessionValue(sessionVariable);
diff --git
a/regression-test/suites/audit/test_audit_log_hint_session_context.groovy
b/regression-test/suites/audit/test_audit_log_hint_session_context.groovy
new file mode 100644
index 00000000000..32ccf653543
--- /dev/null
+++ b/regression-test/suites/audit/test_audit_log_hint_session_context.groovy
@@ -0,0 +1,71 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+// A session variable changed by a per-query SET_VAR hint is temporary: it is
reverted in
+// StmtExecutor.execute()'s finally block. The audit log is built afterwards
(in auditAfterExec),
+// so without a pre-revert snapshot the hint value never reaches
changed_variables. This case
+// verifies that a per-query SET_VAR(session_context=...) is recorded in the
audit log's
+// changed_variables. The value is quoted so the hint parser keeps the ':' in
the value.
+suite("test_audit_log_hint_session_context", "nonConcurrent") {
+ try {
+ sql "set global enable_audit_plugin = true"
+ } catch (Exception e) {
+ log.warn("skip this case, because " + e.getMessage())
+ assertTrue(e.getMessage().toUpperCase().contains("ADMIN"))
+ return
+ }
+
+ def tbl = "audit_hint_session_context"
+ sql "drop table if exists ${tbl}"
+ sql """
+ CREATE TABLE `${tbl}` (`id` bigint) ENGINE=OLAP
+ DUPLICATE KEY(`id`)
+ DISTRIBUTED BY HASH(`id`) BUCKETS 1
+ PROPERTIES ("replication_allocation" = "tag.location.default: 1")
+ """
+ sql "insert into ${tbl} values (1)"
+
+ // unique markers so the exact statement can be located in the audit log
+ def hintTrace = "trace_id:hint_sc_7F3A2B"
+ def stmtMarker = "audit_hint_sc_marker_7F3A2B"
+
+ sql "truncate table __internal_schema.audit_log"
+
+ // per-query SET_VAR hint sets session_context for this statement only
+ sql """select /*+ SET_VAR(session_context="${hintTrace}") */ id,
'${stmtMarker}' as marker from ${tbl}"""
+
+ Thread.sleep(6000)
+ sql """call flush_audit_log()"""
+
+ def retry = 180
+ def query = """select ELEMENT_AT(changed_variables, 'session_context')
+ from __internal_schema.audit_log
+ where stmt like '%${stmtMarker}%' order by time desc limit
1"""
+ def res = sql "${query}"
+ while (res.isEmpty()) {
+ if (retry-- < 0) {
+ throw new RuntimeException("audit_log row for the hint query was
not found")
+ }
+ sleep(3000)
+ res = sql "${query}"
+ }
+
+ // The per-query SET_VAR hint session_context must be visible in
changed_variables.
+ assertEquals(hintTrace, res[0][0].toString())
+
+ sql "set global enable_audit_plugin = false"
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]