Skip to content

Commit dffbd3e

Browse files
authored
*: support logging session connect attrs to slow query log (#66617)
close #66616
1 parent 820a41f commit dffbd3e

24 files changed

Lines changed: 1088 additions & 17 deletions

pkg/executor/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ go_test(
499499
"//pkg/testkit/testfailpoint",
500500
"//pkg/testkit/testmain",
501501
"//pkg/testkit/testsetup",
502+
"//pkg/testkit/testutil",
502503
"//pkg/types",
503504
"//pkg/util",
504505
"//pkg/util/benchdaily",

pkg/executor/adapter_slow_log.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,9 @@ func SetSlowLogItems(a *ExecStmt, txnTS uint64, hasMoreResults bool, items *vari
270270
items.StorageKV = stmtCtx.IsTiKV.Load()
271271
items.StorageMPP = stmtCtx.IsTiFlash.Load()
272272
items.MemArbitration = stmtCtx.MemTracker.MemArbitration().Seconds()
273+
if sessVars.ConnectionInfo != nil && len(sessVars.ConnectionInfo.Attributes) > 0 {
274+
items.SessionConnectAttrs = sessVars.ConnectionInfo.Attributes
275+
}
273276

274277
if a.retryCount > 0 {
275278
items.ExecRetryTime = items.TimeTotal - sessVars.DurationParse - sessVars.DurationCompile - time.Since(a.retryStartTime)

pkg/executor/cluster_table_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import (
3535
"github.com/pingcap/tidb/pkg/server"
3636
"github.com/pingcap/tidb/pkg/session/sessmgr"
3737
"github.com/pingcap/tidb/pkg/testkit"
38+
"github.com/pingcap/tidb/pkg/testkit/testutil"
3839
"github.com/stretchr/testify/require"
3940
"google.golang.org/grpc"
4041
)
@@ -391,3 +392,38 @@ func removeFiles(t *testing.T, fileNames []string) {
391392
require.NoError(t, os.Remove(fileName))
392393
}
393394
}
395+
396+
func TestClusterTableSlowQuerySessionConnectAttrs(t *testing.T) {
397+
store, dom := testkit.CreateMockStoreAndDomain(t)
398+
srv := createRPCServer(t, dom)
399+
defer srv.Stop()
400+
401+
logData := `
402+
# Time: 2024-01-15T10:00:00.000000+08:00
403+
# Txn_start_ts: 123456789
404+
# User@Host: root[root] @ localhost [127.0.0.1]
405+
# Query_time: 0.5
406+
# Digest: 42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772
407+
# Is_internal: false
408+
# Succ: true
409+
` + testutil.DefaultSessionConnectAttrsSlowLogLine() + `
410+
select * from t;`
411+
fileName := "tidb-slow-query-attrs.log"
412+
prepareLogs(t, []string{logData}, []string{fileName})
413+
defer removeFiles(t, []string{fileName})
414+
415+
defer config.RestoreFunc()()
416+
config.UpdateGlobal(func(conf *config.Config) {
417+
conf.Log.SlowQueryFile = fileName
418+
})
419+
420+
tk := testkit.NewTestKit(t, store)
421+
tk.MustExec("use information_schema")
422+
423+
// Verify Session_connect_attrs column is present in cluster_slow_query as well.
424+
clusterRows := tk.MustQuery("select Session_connect_attrs from information_schema.cluster_slow_query " +
425+
"where time > '2024-01-01 00:00:00' and query = 'select * from t;'").Rows()
426+
require.Len(t, clusterRows, 1)
427+
clusterAttrsStr := clusterRows[0][0].(string)
428+
testutil.RequireContainsDefaultSessionConnectAttrs(t, clusterAttrsStr)
429+
}

pkg/executor/slow_query.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,9 @@ func (e *slowQueryRetriever) parseLog(ctx context.Context, sctx sessionctx.Conte
982982
} else if strings.HasPrefix(line, variable.SlowLogWarnings+variable.SlowLogSpaceMarkStr) {
983983
line = line[len(variable.SlowLogWarnings+variable.SlowLogSpaceMarkStr):]
984984
valid = e.setColumnValue(sctx, row, tz, variable.SlowLogWarnings, line, e.checker, fileLine)
985+
} else if strings.HasPrefix(line, variable.SlowLogSessionConnectAttrs+variable.SlowLogSpaceMarkStr) {
986+
line = line[len(variable.SlowLogSessionConnectAttrs+variable.SlowLogSpaceMarkStr):]
987+
valid = e.setColumnValue(sctx, row, tz, variable.SlowLogSessionConnectAttrs, line, e.checker, fileLine)
985988
} else if strings.HasPrefix(line, variable.SlowLogDBStr+variable.SlowLogSpaceMarkStr) {
986989
line = line[len(variable.SlowLogDBStr+variable.SlowLogSpaceMarkStr):]
987990
valid = e.setColumnValue(sctx, row, tz, variable.SlowLogDBStr, line, e.checker, fileLine)
@@ -1170,6 +1173,18 @@ func getColumnValueFactoryByName(colName string, columnIdx int) (slowQueryColumn
11701173
row[columnIdx] = types.NewDatum(v)
11711174
return true, nil
11721175
}, nil
1176+
case variable.SlowLogSessionConnectAttrs:
1177+
return func(row []types.Datum, value string, _ *time.Location, _ *slowLogChecker) (valid bool, err error) {
1178+
if len(value) == 0 {
1179+
return true, nil
1180+
}
1181+
bj, err := types.ParseBinaryJSONFromString(value)
1182+
if err != nil {
1183+
return false, err
1184+
}
1185+
row[columnIdx] = types.NewDatum(bj)
1186+
return true, nil
1187+
}, nil
11731188
}
11741189
return nil, nil
11751190
}

pkg/executor/slow_query_sql_test.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"github.com/pingcap/tidb/pkg/testkit"
3232
"github.com/pingcap/tidb/pkg/testkit/external"
3333
"github.com/pingcap/tidb/pkg/testkit/testdata"
34+
"github.com/pingcap/tidb/pkg/testkit/testutil"
3435
"github.com/pingcap/tidb/pkg/util/logutil"
3536
"github.com/stretchr/testify/require"
3637
)
@@ -544,3 +545,98 @@ func TestStorageEnginesInSlowQuery(t *testing.T) {
544545
"where query like 'select%tablesample%;'").
545546
Check(testkit.Rows("1 0"))
546547
}
548+
549+
func TestSessionConnectAttrsInSlowQuery(t *testing.T) {
550+
originCfg := config.GetGlobalConfig()
551+
newCfg := *originCfg
552+
f, err := os.CreateTemp("", "tidb-slow-*.log")
553+
require.NoError(t, err)
554+
_, err = f.WriteString(`# Time: 2024-01-15T10:00:00.000000+08:00
555+
# Txn_start_ts: 123456789
556+
# User@Host: root[root] @ localhost [127.0.0.1]
557+
# Query_time: 0.5
558+
# Digest: 42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772
559+
# Is_internal: false
560+
# Succ: true
561+
` + testutil.DefaultSessionConnectAttrsSlowLogLine() + `
562+
select * from t;
563+
`)
564+
require.NoError(t, err)
565+
require.NoError(t, f.Close())
566+
newCfg.Log.SlowQueryFile = f.Name()
567+
config.StoreGlobalConfig(&newCfg)
568+
defer func() {
569+
config.StoreGlobalConfig(originCfg)
570+
require.NoError(t, os.Remove(newCfg.Log.SlowQueryFile))
571+
}()
572+
require.NoError(t, logutil.InitLogger(newCfg.Log.ToLogConfig()))
573+
store := testkit.CreateMockStore(t)
574+
tk := testkit.NewTestKit(t, store)
575+
576+
tk.MustExec("set @@time_zone='+08:00'")
577+
tk.MustExec(fmt.Sprintf("set @@tidb_slow_query_file='%v'", f.Name()))
578+
579+
// Verify Session_connect_attrs column is present and returns the correct JSON value.
580+
rows := tk.MustQuery("select Session_connect_attrs from information_schema.slow_query " +
581+
"where query = 'select * from t;'").Rows()
582+
require.Len(t, rows, 1)
583+
attrsStr := rows[0][0].(string)
584+
testutil.RequireContainsDefaultSessionConnectAttrs(t, attrsStr)
585+
586+
// Verify individual keys are accessible via JSON_EXTRACT.
587+
tk.MustQuery("select JSON_EXTRACT(Session_connect_attrs, '$._client_name') from information_schema.slow_query " +
588+
"where query = 'select * from t;'").
589+
Check(testkit.Rows(`"Go-MySQL-Driver"`))
590+
tk.MustQuery("select JSON_EXTRACT(Session_connect_attrs, '$.app_name') from information_schema.slow_query " +
591+
"where query = 'select * from t;'").
592+
Check(testkit.Rows(`"test_app"`))
593+
}
594+
595+
func TestSessionConnectAttrsMissingAndTruncatedInSlowQuery(t *testing.T) {
596+
originCfg := config.GetGlobalConfig()
597+
newCfg := *originCfg
598+
f, err := os.CreateTemp("", "tidb-slow-*.log")
599+
require.NoError(t, err)
600+
_, err = f.WriteString(`# Time: 2024-01-15T10:00:00.000000+08:00
601+
# Txn_start_ts: 123456789
602+
# User@Host: root[root] @ localhost [127.0.0.1]
603+
# Query_time: 0.5
604+
# Digest: 1111111111111111111111111111111111111111111111111111111111111111
605+
# Is_internal: false
606+
# Succ: true
607+
select * from t_no_attrs;
608+
# Time: 2024-01-15T10:00:01.000000+08:00
609+
# Txn_start_ts: 123456790
610+
# User@Host: root[root] @ localhost [127.0.0.1]
611+
# Query_time: 0.6
612+
# Digest: 2222222222222222222222222222222222222222222222222222222222222222
613+
# Is_internal: false
614+
# Succ: true
615+
# Session_connect_attrs: {"_truncated":"4","app_name":"trunc_case"}
616+
select * from t_truncated;
617+
`)
618+
require.NoError(t, err)
619+
require.NoError(t, f.Close())
620+
newCfg.Log.SlowQueryFile = f.Name()
621+
config.StoreGlobalConfig(&newCfg)
622+
defer func() {
623+
config.StoreGlobalConfig(originCfg)
624+
require.NoError(t, os.Remove(newCfg.Log.SlowQueryFile))
625+
}()
626+
require.NoError(t, logutil.InitLogger(newCfg.Log.ToLogConfig()))
627+
store := testkit.CreateMockStore(t)
628+
tk := testkit.NewTestKit(t, store)
629+
630+
tk.MustExec("set @@time_zone='+08:00'")
631+
tk.MustExec(fmt.Sprintf("set @@tidb_slow_query_file='%v'", f.Name()))
632+
633+
// Missing Session_connect_attrs should parse to JSON null-like empty behavior.
634+
tk.MustQuery("select Session_connect_attrs = cast('null' as json), JSON_EXTRACT(Session_connect_attrs, '$._truncated') is null from information_schema.slow_query " +
635+
"where query = 'select * from t_no_attrs;' ").
636+
Check(testkit.Rows("1 1"))
637+
638+
// Truncation metadata key should be preserved and queryable from JSON.
639+
tk.MustQuery("select JSON_UNQUOTE(JSON_EXTRACT(Session_connect_attrs, '$._truncated')), JSON_UNQUOTE(JSON_EXTRACT(Session_connect_attrs, '$.app_name')) from information_schema.slow_query " +
640+
"where query = 'select * from t_truncated;' ").
641+
Check(testkit.Rows("4 trunc_case"))
642+
}

pkg/executor/slow_query_test.go

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import (
3737
"github.com/pingcap/tidb/pkg/sessionctx"
3838
"github.com/pingcap/tidb/pkg/sessionctx/vardef"
3939
"github.com/pingcap/tidb/pkg/sessionctx/variable"
40+
"github.com/pingcap/tidb/pkg/testkit/testutil"
4041
"github.com/pingcap/tidb/pkg/types"
4142
"github.com/pingcap/tidb/pkg/util"
4243
"github.com/pingcap/tidb/pkg/util/logutil"
@@ -191,7 +192,7 @@ select * from t;`
191192
`0.1,0.2,0.03,127.0.0.1:20160,0.05,0.6,0.8,0.0.0.0:20160,70724,23333,65536,0,0,0,30000,3000,10000,1000,500000,500005,300000,300005,0,0,,` +
192193
`Cop_backoff_regionMiss_total_times: 200 Cop_backoff_regionMiss_total_time: 0.2 Cop_backoff_regionMiss_max_time: 0.2 Cop_backoff_regionMiss_max_addr: 127.0.0.1 Cop_backoff_regionMiss_avg_time: 0.2 Cop_backoff_regionMiss_p90_time: 0.2 Cop_backoff_rpcPD_total_times: 200 Cop_backoff_rpcPD_total_time: 0.2 Cop_backoff_rpcPD_max_time: 0.2 Cop_backoff_rpcPD_max_addr: 127.0.0.1 Cop_backoff_rpcPD_avg_time: 0.2 Cop_backoff_rpcPD_p90_time: 0.2 Cop_backoff_rpcTiKV_total_times: 200 Cop_backoff_rpcTiKV_total_time: 0.2 Cop_backoff_rpcTiKV_max_time: 0.2 Cop_backoff_rpcTiKV_max_addr: 127.0.0.1 Cop_backoff_rpcTiKV_avg_time: 0.2 Cop_backoff_rpcTiKV_p90_time: 0.2,` +
193194
`0,0,1,0,1,1,0,default,2.158,2.123,0.05,0.01,0.021,1,1,,,60e9378c746d9a2be1c791047e008967cf252eb6de9167ad3aa6098fa2d523f4,` +
194-
`,update t set i = 1;,select * from t;`
195+
`,update t set i = 1;,null,select * from t;`
195196
require.Equal(t, expectRecordString, recordString)
196197

197198
// Issue 20928
@@ -214,7 +215,7 @@ select * from t;`
214215
`0.1,0.2,0.03,127.0.0.1:20160,0.05,0.6,0.8,0.0.0.0:20160,70724,23333,65536,0,0,0,30000,3000,10000,1000,500000,500005,300000,300005,0,0,,` +
215216
`Cop_backoff_regionMiss_total_times: 200 Cop_backoff_regionMiss_total_time: 0.2 Cop_backoff_regionMiss_max_time: 0.2 Cop_backoff_regionMiss_max_addr: 127.0.0.1 Cop_backoff_regionMiss_avg_time: 0.2 Cop_backoff_regionMiss_p90_time: 0.2 Cop_backoff_rpcPD_total_times: 200 Cop_backoff_rpcPD_total_time: 0.2 Cop_backoff_rpcPD_max_time: 0.2 Cop_backoff_rpcPD_max_addr: 127.0.0.1 Cop_backoff_rpcPD_avg_time: 0.2 Cop_backoff_rpcPD_p90_time: 0.2 Cop_backoff_rpcTiKV_total_times: 200 Cop_backoff_rpcTiKV_total_time: 0.2 Cop_backoff_rpcTiKV_max_time: 0.2 Cop_backoff_rpcTiKV_max_addr: 127.0.0.1 Cop_backoff_rpcTiKV_avg_time: 0.2 Cop_backoff_rpcTiKV_p90_time: 0.2,` +
216217
`0,0,1,0,1,1,0,default,2.158,2.123,0.05,0.01,0.021,1,1,,,60e9378c746d9a2be1c791047e008967cf252eb6de9167ad3aa6098fa2d523f4,` +
217-
`,update t set i = 1;,select * from t;`
218+
`,update t set i = 1;,null,select * from t;`
218219
require.Equal(t, expectRecordString, recordString)
219220

220221
// fix sql contain '# ' bug
@@ -284,6 +285,57 @@ select * from t;
284285
require.Equal(t, value, "[t:i: a]")
285286
}
286287

288+
func TestParseSlowLogSessionConnectAttrs(t *testing.T) {
289+
// Slow log entry that includes Session_connect_attrs JSON.
290+
slowLogStr := `# Time: 2019-04-28T15:24:04.309074+08:00
291+
# Txn_start_ts: 405888132465033227
292+
# User@Host: root[root] @ localhost [127.0.0.1]
293+
# Query_time: 0.216905
294+
# Digest: 42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772
295+
# Is_internal: false
296+
# Succ: true
297+
` + testutil.DefaultSessionConnectAttrsSlowLogLine() + `
298+
# Prev_stmt: begin;
299+
select * from t;
300+
`
301+
loc, err := time.LoadLocation("Asia/Shanghai")
302+
require.NoError(t, err)
303+
ctx := mock.NewContext()
304+
ctx.ResetSessionAndStmtTimeZone(loc)
305+
306+
// Use the retriever directly (without initialize) to avoid reading
307+
// from actual slow log files on disk, which can produce extra rows.
308+
retriever, err := newSlowQueryRetriever()
309+
require.NoError(t, err)
310+
retriever.columnValueFactoryMap = make(map[string]slowQueryColumnValueFactory, len(retriever.outputCols))
311+
for idx, col := range retriever.outputCols {
312+
factory, err := getColumnValueFactoryByName(col.Name.O, idx)
313+
require.NoError(t, err)
314+
require.NotNil(t, factory, "column %s should have a factory", col.Name.O)
315+
retriever.columnValueFactoryMap[col.Name.O] = factory
316+
}
317+
318+
reader := bufio.NewReader(bytes.NewBufferString(slowLogStr))
319+
rows, err := parseLog(retriever, ctx, reader)
320+
require.NoError(t, err)
321+
require.Len(t, rows, 1)
322+
323+
// Find the Session_connect_attrs column.
324+
colIdx := -1
325+
for i, col := range retriever.outputCols {
326+
if col.Name.L == strings.ToLower(variable.SlowLogSessionConnectAttrs) {
327+
colIdx = i
328+
break
329+
}
330+
}
331+
require.NotEqual(t, -1, colIdx, "Session_connect_attrs column should exist")
332+
333+
// Verify the parsed JSON contains the expected keys.
334+
bj := rows[0][colIdx].GetMysqlJSON()
335+
bjStr := bj.String()
336+
testutil.RequireContainsDefaultSessionConnectAttrs(t, bjStr)
337+
}
338+
287339
// It changes variable.MaxOfMaxAllowedPacket, so must be stayed in SerialSuite.
288340
func TestParseSlowLogFileSerial(t *testing.T) {
289341
loc, err := time.LoadLocation("Asia/Shanghai")

pkg/infoschema/tables.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,7 @@ var slowQueryCols = []columnInfo{
984984
{name: variable.SlowLogPlanDigest, tp: mysql.TypeVarchar, size: 128},
985985
{name: variable.SlowLogBinaryPlan, tp: mysql.TypeLongBlob, size: types.UnspecifiedLength},
986986
{name: variable.SlowLogPrevStmt, tp: mysql.TypeLongBlob, size: types.UnspecifiedLength},
987+
{name: variable.SlowLogSessionConnectAttrs, tp: mysql.TypeJSON, size: types.UnspecifiedLength},
987988
{name: variable.SlowLogQuerySQLStr, tp: mysql.TypeLongBlob, size: types.UnspecifiedLength},
988989
}
989990

pkg/infoschema/test/clustertablestest/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ go_test(
4141
"//pkg/testkit",
4242
"//pkg/testkit/external",
4343
"//pkg/testkit/testsetup",
44+
"//pkg/testkit/testutil",
4445
"//pkg/types",
4546
"//pkg/util/dbterror/exeerrors",
4647
"//pkg/util/gctuner",

pkg/infoschema/test/clustertablestest/cluster_tables_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ import (
5151
"github.com/pingcap/tidb/pkg/store/mockstore/unistore"
5252
"github.com/pingcap/tidb/pkg/testkit"
5353
"github.com/pingcap/tidb/pkg/testkit/external"
54+
"github.com/pingcap/tidb/pkg/testkit/testutil"
5455
"github.com/pingcap/tidb/pkg/util/dbterror/exeerrors"
5556
"github.com/pingcap/tidb/pkg/util/logutil"
5657
"github.com/pingcap/tidb/pkg/util/set"
@@ -291,6 +292,55 @@ func TestSelectClusterTable(t *testing.T) {
291292
tk.MustQuery("select instance from `CLUSTER_SLOW_QUERY` where time='2019-02-12 19:33:56.571953'").Check(testkit.Rows(instanceAddr))
292293
}
293294

295+
func TestClusterSlowQuerySessionConnectAttrs(t *testing.T) {
296+
// setup suite
297+
s := new(clusterTablesSuite)
298+
s.store, s.dom = testkit.CreateMockStoreAndDomain(t)
299+
s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0", nil)
300+
s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer()
301+
s.startTime = time.Now()
302+
defer s.httpServer.Close()
303+
defer s.rpcserver.Stop()
304+
305+
f, err := os.CreateTemp("", "tidb-cluster-slow-*.log")
306+
require.NoError(t, err)
307+
_, err = f.WriteString(`# Time: 2024-01-15T10:00:00.000000+08:00
308+
# Txn_start_ts: 123456789
309+
# User@Host: root[root] @ localhost [127.0.0.1]
310+
# Query_time: 0.5
311+
# Digest: 42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772
312+
# Is_internal: false
313+
# Succ: true
314+
` + testutil.DefaultSessionConnectAttrsSlowLogLine() + `
315+
select * from t;
316+
`)
317+
require.NoError(t, err)
318+
require.NoError(t, f.Close())
319+
defer func() { require.NoError(t, os.Remove(f.Name())) }()
320+
321+
defer config.RestoreFunc()()
322+
config.UpdateGlobal(func(conf *config.Config) {
323+
conf.Log.SlowQueryFile = f.Name()
324+
})
325+
326+
tk := s.newTestKitWithRoot(t)
327+
tk.MustExec("use information_schema")
328+
tk.MustExec("set time_zone = '+08:00';")
329+
330+
rows := tk.MustQuery("select Session_connect_attrs from information_schema.cluster_slow_query " +
331+
"where query = 'select * from t;'").Rows()
332+
require.Len(t, rows, 1)
333+
attrsStr := rows[0][0].(string)
334+
testutil.RequireContainsDefaultSessionConnectAttrs(t, attrsStr)
335+
336+
tk.MustQuery("select JSON_EXTRACT(Session_connect_attrs, '$._client_name') from information_schema.cluster_slow_query " +
337+
"where query = 'select * from t;'").
338+
Check(testkit.Rows(`"Go-MySQL-Driver"`))
339+
tk.MustQuery("select JSON_EXTRACT(Session_connect_attrs, '$.app_name') from information_schema.cluster_slow_query " +
340+
"where query = 'select * from t;'").
341+
Check(testkit.Rows(`"test_app"`))
342+
}
343+
294344
func TestSelectClusterTablePrivilege(t *testing.T) {
295345
// setup suite
296346
s := new(clusterTablesSuite)

pkg/infoschema/test/clustertablestest/tables_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,7 @@ func TestSlowQuery(t *testing.T) {
496496
"60e9378c746d9a2be1c791047e008967cf252eb6de9167ad3aa6098fa2d523f4",
497497
"",
498498
"update t set i = 2;",
499+
"null",
499500
"select * from t_slim;",
500501
},
501502
{"2021-09-08 14:39:54.506967",
@@ -590,6 +591,7 @@ func TestSlowQuery(t *testing.T) {
590591
"",
591592
"",
592593
"",
594+
"null",
593595
"INSERT INTO ...;",
594596
},
595597
}

0 commit comments

Comments
 (0)