Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 1145c26

Browse files
committed
Advance transaction timestamp for intra-procedure transactions.
Per discussion, this behavior seems less astonishing than not doing so. Peter Eisentraut and Tom Lane Discussion: https://postgr.es/m/20180920234040.GC29981@momjian.us
1 parent 8569ef6 commit 1145c26

File tree

5 files changed

+91
-8
lines changed

5 files changed

+91
-8
lines changed

src/backend/access/transam/xact.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1906,20 +1906,26 @@ StartTransaction(void)
19061906
TRACE_POSTGRESQL_TRANSACTION_START(vxid.localTransactionId);
19071907

19081908
/*
1909-
* set transaction_timestamp() (a/k/a now()). We want this to be the same
1910-
* as the first command's statement_timestamp(), so don't do a fresh
1911-
* GetCurrentTimestamp() call (which'd be expensive anyway). In a
1912-
* parallel worker, this should already have been provided by a call to
1909+
* set transaction_timestamp() (a/k/a now()). Normally, we want this to
1910+
* be the same as the first command's statement_timestamp(), so don't do a
1911+
* fresh GetCurrentTimestamp() call (which'd be expensive anyway). But
1912+
* for transactions started inside procedures (i.e., nonatomic SPI
1913+
* contexts), we do need to advance the timestamp. Also, in a parallel
1914+
* worker, the timestamp should already have been provided by a call to
19131915
* SetParallelStartTimestamps().
1914-
*
1915-
* Also, mark xactStopTimestamp as unset.
19161916
*/
19171917
if (!IsParallelWorker())
1918-
xactStartTimestamp = stmtStartTimestamp;
1918+
{
1919+
if (!SPI_inside_nonatomic_context())
1920+
xactStartTimestamp = stmtStartTimestamp;
1921+
else
1922+
xactStartTimestamp = GetCurrentTimestamp();
1923+
}
19191924
else
19201925
Assert(xactStartTimestamp != 0);
1921-
xactStopTimestamp = 0;
19221926
pgstat_report_xact_timestamp(xactStartTimestamp);
1927+
/* Mark xactStopTimestamp as unset. */
1928+
xactStopTimestamp = 0;
19231929

19241930
/*
19251931
* initialize current transaction state fields

src/backend/executor/spi.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,19 @@ AtEOSubXact_SPI(bool isCommit, SubTransactionId mySubid)
423423
}
424424
}
425425

426+
/*
427+
* Are we executing inside a procedure (that is, a nonatomic SPI context)?
428+
*/
429+
bool
430+
SPI_inside_nonatomic_context(void)
431+
{
432+
if (_SPI_current == NULL)
433+
return false; /* not in any SPI context at all */
434+
if (_SPI_current->atomic)
435+
return false; /* it's atomic (ie function not procedure) */
436+
return true;
437+
}
438+
426439

427440
/* Parse, plan, and execute a query string */
428441
int

src/include/executor/spi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,5 +166,6 @@ extern void SPI_rollback(void);
166166
extern void SPICleanup(void);
167167
extern void AtEOXact_SPI(bool isCommit);
168168
extern void AtEOSubXact_SPI(bool isCommit, SubTransactionId mySubid);
169+
extern bool SPI_inside_nonatomic_context(void);
169170

170171
#endif /* SPI_H */

src/pl/plpgsql/src/expected/plpgsql_transaction.out

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,36 @@ CALL transaction_test10b(10);
493493
9
494494
(1 row)
495495

496+
-- transaction timestamp vs. statement timestamp
497+
CREATE PROCEDURE transaction_test11()
498+
LANGUAGE plpgsql
499+
AS $$
500+
DECLARE
501+
s1 timestamp with time zone;
502+
s2 timestamp with time zone;
503+
s3 timestamp with time zone;
504+
t1 timestamp with time zone;
505+
t2 timestamp with time zone;
506+
t3 timestamp with time zone;
507+
BEGIN
508+
s1 := statement_timestamp();
509+
t1 := transaction_timestamp();
510+
ASSERT s1 = t1;
511+
PERFORM pg_sleep(0.001);
512+
COMMIT;
513+
s2 := statement_timestamp();
514+
t2 := transaction_timestamp();
515+
ASSERT s2 = s1;
516+
ASSERT t2 > t1;
517+
PERFORM pg_sleep(0.001);
518+
ROLLBACK;
519+
s3 := statement_timestamp();
520+
t3 := transaction_timestamp();
521+
ASSERT s3 = s1;
522+
ASSERT t3 > t2;
523+
END;
524+
$$;
525+
CALL transaction_test11();
496526
DROP TABLE test1;
497527
DROP TABLE test2;
498528
DROP TABLE test3;

src/pl/plpgsql/src/sql/plpgsql_transaction.sql

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,39 @@ $$;
412412
CALL transaction_test10b(10);
413413

414414

415+
-- transaction timestamp vs. statement timestamp
416+
CREATE PROCEDURE transaction_test11()
417+
LANGUAGE plpgsql
418+
AS $$
419+
DECLARE
420+
s1 timestamp with time zone;
421+
s2 timestamp with time zone;
422+
s3 timestamp with time zone;
423+
t1 timestamp with time zone;
424+
t2 timestamp with time zone;
425+
t3 timestamp with time zone;
426+
BEGIN
427+
s1 := statement_timestamp();
428+
t1 := transaction_timestamp();
429+
ASSERT s1 = t1;
430+
PERFORM pg_sleep(0.001);
431+
COMMIT;
432+
s2 := statement_timestamp();
433+
t2 := transaction_timestamp();
434+
ASSERT s2 = s1;
435+
ASSERT t2 > t1;
436+
PERFORM pg_sleep(0.001);
437+
ROLLBACK;
438+
s3 := statement_timestamp();
439+
t3 := transaction_timestamp();
440+
ASSERT s3 = s1;
441+
ASSERT t3 > t2;
442+
END;
443+
$$;
444+
445+
CALL transaction_test11();
446+
447+
415448
DROP TABLE test1;
416449
DROP TABLE test2;
417450
DROP TABLE test3;

0 commit comments

Comments
 (0)