PGPROC *parallel_master_pgproc;
pid_t parallel_master_pid;
BackendId parallel_master_backend_id;
+ TimestampTz xact_ts;
+ TimestampTz stmt_ts;
/* Mutex protects remaining fields. */
slock_t mutex;
fps->parallel_master_pgproc = MyProc;
fps->parallel_master_pid = MyProcPid;
fps->parallel_master_backend_id = MyBackendId;
+ fps->xact_ts = GetCurrentTransactionStartTimestamp();
+ fps->stmt_ts = GetCurrentStatementStartTimestamp();
SpinLockInit(&fps->mutex);
fps->last_xlog_end = 0;
shm_toc_insert(pcxt->toc, PARALLEL_KEY_FIXED, fps);
fps->parallel_master_pid))
return;
+ /*
+ * Restore transaction and statement start-time timestamps. This must
+ * happen before anything that would start a transaction, else asserts in
+ * xact.c will fire.
+ */
+ SetParallelStartTimestamps(fps->xact_ts, fps->stmt_ts);
+
/*
* Identify the entry point to be called. In theory this could result in
* loading an additional library, though most likely the entry point is in
return currentCommandId;
}
+/*
+ * SetParallelStartTimestamps
+ *
+ * In a parallel worker, we should inherit the parent transaction's
+ * timestamps rather than setting our own. The parallel worker
+ * infrastructure must call this to provide those values before
+ * calling StartTransaction() or SetCurrentStatementStartTimestamp().
+ */
+void
+SetParallelStartTimestamps(TimestampTz xact_ts, TimestampTz stmt_ts)
+{
+ Assert(IsParallelWorker());
+ xactStartTimestamp = xact_ts;
+ stmtStartTimestamp = stmt_ts;
+}
+
/*
* GetCurrentTransactionStartTimestamp
*/
/*
* SetCurrentStatementStartTimestamp
+ *
+ * In a parallel worker, this should already have been provided by a call
+ * to SetParallelStartTimestamps().
*/
void
SetCurrentStatementStartTimestamp(void)
{
- stmtStartTimestamp = GetCurrentTimestamp();
+ if (!IsParallelWorker())
+ stmtStartTimestamp = GetCurrentTimestamp();
+ else
+ Assert(stmtStartTimestamp != 0);
}
/*
/*
* set transaction_timestamp() (a/k/a now()). We want this to be the same
* as the first command's statement_timestamp(), so don't do a fresh
- * GetCurrentTimestamp() call (which'd be expensive anyway). Also, mark
- * xactStopTimestamp as unset.
+ * GetCurrentTimestamp() call (which'd be expensive anyway). In a
+ * parallel worker, this should already have been provided by a call to
+ * SetParallelStartTimestamps().
+ *
+ * Also, mark xactStopTimestamp as unset.
*/
- xactStartTimestamp = stmtStartTimestamp;
+ if (!IsParallelWorker())
+ xactStartTimestamp = stmtStartTimestamp;
+ else
+ Assert(xactStartTimestamp != 0);
xactStopTimestamp = 0;
pgstat_report_xact_timestamp(xactStartTimestamp);
{ oid => '1365', descr => 'make ACL item',
proname => 'makeaclitem', prorettype => 'aclitem',
proargtypes => 'oid oid text bool', prosrc => 'makeaclitem' },
-{ oid => '3943', descr => 'show hardwired default privileges, primarily for use by the information schema',
+{ oid => '3943',
+ descr => 'show hardwired default privileges, primarily for use by the information schema',
proname => 'acldefault', prorettype => '_aclitem', proargtypes => 'char oid',
prosrc => 'acldefault_sql' },
{ oid => '1689',
proname => 'timetzdate_pl', prolang => '14', prorettype => 'timestamptz',
proargtypes => 'timetz date', prosrc => 'select ($2 + $1)' },
{ oid => '1299', descr => 'current transaction time',
- proname => 'now', provolatile => 's', proparallel => 'r',
- prorettype => 'timestamptz', proargtypes => '', prosrc => 'now' },
+ proname => 'now', provolatile => 's', prorettype => 'timestamptz',
+ proargtypes => '', prosrc => 'now' },
{ oid => '2647', descr => 'current transaction time',
proname => 'transaction_timestamp', provolatile => 's',
prorettype => 'timestamptz', proargtypes => '', prosrc => 'now' },
{ oid => '2648', descr => 'current statement time',
- proname => 'statement_timestamp', provolatile => 's', proparallel => 'r',
+ proname => 'statement_timestamp', provolatile => 's',
prorettype => 'timestamptz', proargtypes => '',
prosrc => 'statement_timestamp' },
{ oid => '2649', descr => 'current clock time',
proname => 'pg_ls_tmpdir', procost => '10', prorows => '20', proretset => 't',
provolatile => 'v', prorettype => 'record', proargtypes => 'oid',
proallargtypes => '{oid,text,int8,timestamptz}', proargmodes => '{i,o,o,o}',
- proargnames => '{tablespace,name,size,modification}', prosrc => 'pg_ls_tmpdir_1arg' },
+ proargnames => '{tablespace,name,size,modification}',
+ prosrc => 'pg_ls_tmpdir_1arg' },
# hash partitioning constraint function
{ oid => '5028', descr => 'hash partition CHECK constraint',