Skip to content

Commit 00997dc

Browse files
committed
Fix jit behavior, fix Fetch stmt behavior
1 parent 8184473 commit 00997dc

File tree

3 files changed

+166
-4
lines changed

3 files changed

+166
-4
lines changed

src/trace_execute_nodes.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,10 +266,10 @@ ExecInitExprRetFunc(void *data, ExprState *resNode)
266266
exprData->traceData.maxTime = 0;
267267
exprData->traceData.totalCalls = 0;
268268
exprData->traceData.totalTimeSum = 0;
269-
exprData->traceData.evalfunc = resNode->evalfunc_private;
269+
exprData->traceData.evalfunc = resNode->evalfunc;
270270
exprData->traceData.tag = resNode->expr->type;
271271
ListAdd(currentState->uprobeExprData, exprData);
272-
resNode->evalfunc_private = TraceExprNodeHook;
272+
resNode->evalfunc = TraceExprNodeHook;
273273
}
274274

275275

@@ -321,6 +321,12 @@ TraceExprNodeHook(struct ExprState *expression, struct ExprContext *econtext, bo
321321
if (!currentState)
322322
return result; /* This case is for ending session trace */
323323

324+
if (expression->evalfunc != TraceExprNodeHook)
325+
{
326+
exprData->traceData.evalfunc = expression->evalfunc;
327+
expression->evalfunc = TraceExprNodeHook;
328+
}
329+
324330
clock_gettime(CLOCK_MONOTONIC, &time);
325331
timeDiff = time.tv_sec * 1000000000L + time.tv_nsec - startTime;
326332
exprData->traceData.totalCalls++;

src/trace_session.c

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include "commands/explain.h"
99
#include "storage/ipc.h"
1010
#include "storage/proc.h"
11-
11+
#include "tcop/utility.h"
1212
#include "trace_parsing.h"
1313
#include "uprobe_internal.h"
1414
#include "trace_lock_on_buffers.h"
@@ -35,6 +35,7 @@ static volatile Uprobe *lastSetUprobe = NULL;
3535
static ExecutorRun_hook_type prev_ExecutorRun_hook = NULL;
3636
static ExecutorStart_hook_type prev_ExecutorStart_hook = NULL;
3737
static ExecutorFinish_hook_type prev_ExecutorFinish_hook = NULL;
38+
static ProcessUtility_hook_type prev_ProcessUtility_hook = NULL;
3839

3940
bool isExecuteTime = false;
4041

@@ -62,6 +63,14 @@ static void TraceSessionExecutorRun(QueryDesc *queryDesc,
6263
uint64 count,
6364
bool execute_once);
6465
#endif
66+
static void TraceSessionExecutorProcessUtility(PlannedStmt *pstmt,
67+
const char *queryString,
68+
bool readOnlyTree,
69+
ProcessUtilityContext context,
70+
ParamListInfo params,
71+
QueryEnvironment *queryEnv,
72+
DestReceiver *dest,
73+
QueryCompletion *qc);
6574
static void TraceSessionExecutorStart(QueryDesc *queryDesc, int eflags);
6675
static void TraceSessionExecutorFinish(QueryDesc *queryDesc);
6776
static char *ProcessDescBeforeExec(QueryDesc *queryDesc);
@@ -289,6 +298,8 @@ SessionTraceStart(void)
289298
ExecutorStart_hook = TraceSessionExecutorStart;
290299
prev_ExecutorFinish_hook = ExecutorFinish_hook;
291300
ExecutorFinish_hook = TraceSessionExecutorFinish;
301+
prev_ProcessUtility_hook = ProcessUtility_hook;
302+
ProcessUtility_hook = TraceSessionExecutorProcessUtility;
292303
}
293304
PG_CATCH();
294305
{
@@ -464,6 +475,27 @@ ProcessDescBeforeExec(QueryDesc *queryDesc)
464475
return planCopy;
465476
}
466477

478+
static void
479+
CallOriginalExecutorFinish(PlannedStmt *pstmt,
480+
const char *queryString,
481+
bool readOnlyTree,
482+
ProcessUtilityContext context,
483+
ParamListInfo params,
484+
QueryEnvironment *queryEnv,
485+
DestReceiver *dest,
486+
QueryCompletion *qc)
487+
{
488+
if (prev_ProcessUtility_hook)
489+
(*prev_ProcessUtility_hook) (pstmt, queryString, readOnlyTree,
490+
context, params, queryEnv,
491+
dest, qc);
492+
else
493+
standard_ProcessUtility(pstmt, queryString, readOnlyTree,
494+
context, params, queryEnv,
495+
dest, qc);
496+
}
497+
498+
467499
#if PG_MAJORVERSION_NUM >= 18
468500
static void
469501
TraceSessionExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
@@ -601,6 +633,82 @@ TraceSessionExecutorFinish(QueryDesc *queryDesc)
601633
PG_END_TRY();
602634
}
603635

636+
static void
637+
TraceSessionExecutorProcessUtility(PlannedStmt *pstmt,
638+
const char *queryString,
639+
bool readOnlyTree,
640+
ProcessUtilityContext context,
641+
ParamListInfo params,
642+
QueryEnvironment *queryEnv,
643+
DestReceiver *dest,
644+
QueryCompletion *qc)
645+
{
646+
char *planCopy;
647+
struct timespec time;
648+
uint64 executionStarted;
649+
FetchStmt *fetch;
650+
Portal portal;
651+
QueryDesc *queryDesc;
652+
653+
if (nodeTag(pstmt->utilityStmt) != T_FetchStmt)
654+
{
655+
CallOriginalExecutorFinish(pstmt, queryString, readOnlyTree,
656+
context, params, queryEnv,
657+
dest, qc);
658+
659+
return;
660+
}
661+
662+
fetch = (FetchStmt*) pstmt->utilityStmt;
663+
portal = GetPortalByName(fetch->portalname);
664+
665+
if (!PortalIsValid(portal))
666+
{
667+
CallOriginalExecutorFinish(pstmt, queryString, readOnlyTree,
668+
context, params, queryEnv,
669+
dest, qc);
670+
return;
671+
}
672+
673+
queryDesc = portal->queryDesc;
674+
675+
if (writeMode == JSON_WRITE_MODE && !isFirstNodeCall)
676+
{
677+
TracePrintf(",\n");
678+
}
679+
680+
planCopy = BeforeExecution(queryDesc);
681+
682+
clock_gettime(CLOCKTYPE, &time);
683+
executionStarted = time.tv_sec * 1000000000L + time.tv_nsec;
684+
685+
ExecutorRunNestLevel++;
686+
687+
PG_TRY();
688+
{
689+
CallOriginalExecutorFinish(pstmt, queryString, readOnlyTree,
690+
context, params, queryEnv,
691+
dest, qc);
692+
}
693+
PG_FINALLY();
694+
{
695+
uint64 timeDiff;
696+
697+
ExecutorRunNestLevel--;
698+
699+
clock_gettime(CLOCKTYPE, &time);
700+
timeDiff = time.tv_sec * 1000000000L + time.tv_nsec - executionStarted;
701+
if (writeMode == TEXT_WRITE_MODE)
702+
TracePrintf("TRACE. Execution finished for %lu nanosec\n", timeDiff);
703+
else
704+
TracePrintf("\n],\n\"executionTime\": \"%lu nanosec\"\n", timeDiff);
705+
706+
AfterExecution(queryDesc, planCopy);
707+
isFirstNodeCall = false;
708+
}
709+
PG_END_TRY();
710+
}
711+
604712

605713
/* find the plan field in explain jsonb */
606714
static JsonbValue *

tests/test_trace_session.py

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,11 +516,57 @@ def trace_session_correct_executor_finish(node: PostgresNode):
516516
(insert into mlparted (b, a) select s.a, 1 from generate_series(2, 39) s(a) returning tableoid::regclass, *) \
517517
select a, b, min(c), max(c) from ins group by a, b order by 1;")
518518

519+
conn.execute("drop table mlparted")
520+
519521
stop_session_trace(conn)
520522

521523
result = node_read_file_one_line(node, f"/pg_uprobe/trace_file.txt_{conn.pid}")
522524
validate_each_session_trace_result(json.loads(result), conn.pid)
523525

526+
def trace_session_fetch(node: PostgresNode):
527+
with node.connect("postgres", autocommit=True) as conn:
528+
start_session_trace(conn)
529+
530+
conn.execute("CREATE TABLE INT8_TBL(q1 int8, q2 int8)")
531+
532+
conn.execute("INSERT INTO INT8_TBL VALUES \
533+
(' 123 ',' 456'), \
534+
('123 ','4567890123456789'), \
535+
('4567890123456789','123'), \
536+
(+4567890123456789,'4567890123456789'), \
537+
('+4567890123456789','-4567890123456789')")
538+
conn.execute("begin")
539+
conn.execute("create function nochange(int) returns int \
540+
as 'select $1 limit 1' language sql stable")
541+
conn.execute("declare c cursor for select * from int8_tbl limit nochange(3)")
542+
conn.execute("fetch all from c")
543+
conn.execute("move backward all in c")
544+
conn.execute("fetch all from c")
545+
conn.execute("rollback")
546+
stop_session_trace(conn)
547+
548+
result = node_read_file_one_line(node, f"/pg_uprobe/trace_file.txt_{conn.pid}")
549+
validate_each_session_trace_result(json.loads(result), conn.pid)
550+
551+
def trace_session_correct_with_jit(node: PostgresNode):
552+
with node.connect("postgres", autocommit=True) as conn:
553+
conn.execute("set jit to on")
554+
conn.execute("set jit_above_cost to 0.0")
555+
conn.execute("set jit_inline_above_cost to 0.0")
556+
conn.execute("set jit_optimize_above_cost to 0.0")
557+
start_session_trace(conn)
558+
559+
conn.execute("create table mlparted (a int, b int)")
560+
conn.execute("with ins (a, b, c) as \
561+
(insert into mlparted (b, a) select s.a, 1 from generate_series(2, 39) s(a) returning tableoid::regclass, *) \
562+
select a, b, min(c), max(c) from ins group by a, b order by 1;")
563+
564+
conn.execute("drop table mlparted")
565+
566+
stop_session_trace(conn)
567+
568+
result = node_read_file_one_line(node, f"/pg_uprobe/trace_file.txt_{conn.pid}")
569+
validate_each_session_trace_result(json.loads(result), conn.pid)
524570

525571
def run_tests(node: PostgresNode):
526572
test_wrapper(node, trace_current_session_trace)
@@ -537,4 +583,6 @@ def run_tests(node: PostgresNode):
537583
test_wrapper(node, trace_session_pid)
538584
test_wrapper(node, trace_session_plpgsql_functions)
539585
test_wrapper(node, trace_session_plpgsql_functions_exceptions)
540-
test_wrapper(node, trace_session_correct_executor_finish)
586+
test_wrapper(node, trace_session_correct_executor_finish)
587+
test_wrapper(node, trace_session_fetch)
588+
test_wrapper(node, trace_session_correct_with_jit)

0 commit comments

Comments
 (0)