=== Applying patches on top of PostgreSQL commit ID 589eb4c3b309f5eaa7c16592ff4edbbf780671fe === /etc/rc.d/jail: WARNING: Per-jail configuration via jail_* variables is obsolete. Please consider migrating to /etc/jail.conf. Tue Aug 4 18:21:07 UTC 2026 On branch cf/6820 nothing to commit, working tree clean === using 'git am' to apply patch ./v2-0001-pg_stat_lock-add-blocker-mode-dimension.patch === Applying: pg_stat_lock: add blocker mode dimension Using index info to reconstruct a base tree... M src/backend/catalog/system_views.sql M src/backend/storage/lmgr/lock.c M src/backend/storage/lmgr/proc.c M src/backend/utils/activity/pgstat_lock.c M src/backend/utils/adt/pgstatfuncs.c M src/include/catalog/catversion.h M src/include/catalog/pg_proc.dat M src/include/pgstat.h M src/test/regress/expected/rules.out M src/test/regress/expected/stats.out M src/test/regress/sql/stats.sql Falling back to patching base and 3-way merge... Auto-merging src/test/regress/sql/stats.sql Auto-merging src/test/regress/expected/stats.out CONFLICT (content): Merge conflict in src/test/regress/expected/stats.out Auto-merging src/test/regress/expected/rules.out Auto-merging src/include/pgstat.h CONFLICT (content): Merge conflict in src/include/pgstat.h Auto-merging src/include/catalog/pg_proc.dat CONFLICT (content): Merge conflict in src/include/catalog/pg_proc.dat Auto-merging src/include/catalog/catversion.h CONFLICT (content): Merge conflict in src/include/catalog/catversion.h Auto-merging src/backend/utils/adt/pgstatfuncs.c CONFLICT (content): Merge conflict in src/backend/utils/adt/pgstatfuncs.c Auto-merging src/backend/utils/activity/pgstat_lock.c CONFLICT (content): Merge conflict in src/backend/utils/activity/pgstat_lock.c Auto-merging src/backend/storage/lmgr/proc.c CONFLICT (content): Merge conflict in src/backend/storage/lmgr/proc.c Auto-merging src/backend/storage/lmgr/lock.c Auto-merging src/backend/catalog/system_views.sql error: Failed to merge in the changes. hint: Use 'git am --show-current-patch=diff' to see the failed patch Patch failed at 0001 pg_stat_lock: add blocker mode dimension When you have resolved this problem, run "git am --continue". If you prefer to skip this patch, run "git am --skip" instead. To restore the original branch and stop patching, run "git am --abort". === using patch(1) to apply patch ./v2-0001-pg_stat_lock-add-blocker-mode-dimension.patch === patching file src/backend/catalog/system_views.sql patching file src/backend/storage/lmgr/lock.c patching file src/backend/storage/lmgr/proc.c Hunk #1 FAILED at 1613. 1 out of 1 hunk FAILED -- saving rejects to file src/backend/storage/lmgr/proc.c.rej patching file src/backend/utils/activity/pgstat_lock.c Hunk #2 FAILED at 121. 1 out of 2 hunks FAILED -- saving rejects to file src/backend/utils/activity/pgstat_lock.c.rej patching file src/backend/utils/adt/pgstatfuncs.c Hunk #1 FAILED at 1740. Hunk #2 FAILED at 1751. 2 out of 2 hunks FAILED -- saving rejects to file src/backend/utils/adt/pgstatfuncs.c.rej patching file src/include/catalog/catversion.h Hunk #1 FAILED at 57. 1 out of 1 hunk FAILED -- saving rejects to file src/include/catalog/catversion.h.rej patching file src/include/catalog/pg_proc.dat Hunk #1 FAILED at 6061. 1 out of 1 hunk FAILED -- saving rejects to file src/include/catalog/pg_proc.dat.rej patching file src/include/pgstat.h Hunk #3 FAILED at 643. 1 out of 3 hunks FAILED -- saving rejects to file src/include/pgstat.h.rej patching file src/include/storage/lock.h patching file src/test/regress/expected/rules.out Hunk #1 succeeded at 1976 with fuzz 2 (offset 8 lines). patching file src/test/regress/expected/stats.out Hunk #1 FAILED at 2018. Hunk #2 succeeded at 2053 (offset 20 lines). 1 out of 2 hunks FAILED -- saving rejects to file src/test/regress/expected/stats.out.rej patching file src/test/regress/sql/stats.sql Hunk #1 succeeded at 1003 with fuzz 2 (offset 7 lines). Hunk #2 succeeded at 1017 with fuzz 2 (offset 12 lines). Unstaged changes after reset: M src/backend/catalog/system_views.sql M src/backend/storage/lmgr/lock.c M src/backend/utils/activity/pgstat_lock.c M src/include/pgstat.h M src/include/storage/lock.h M src/test/regress/expected/rules.out M src/test/regress/expected/stats.out M src/test/regress/sql/stats.sql Removing src/backend/storage/lmgr/proc.c.rej Removing src/backend/utils/activity/pgstat_lock.c.rej Removing src/backend/utils/adt/pgstatfuncs.c.rej Removing src/include/catalog/catversion.h.rej Removing src/include/catalog/pg_proc.dat.rej Removing src/include/pgstat.h.rej Removing src/test/regress/expected/stats.out.rej === using 'git apply' to apply patch ./v2-0001-pg_stat_lock-add-blocker-mode-dimension.patch === Applied patch to 'src/backend/catalog/system_views.sql' cleanly. Applied patch to 'src/backend/storage/lmgr/lock.c' cleanly. Applied patch to 'src/backend/storage/lmgr/proc.c' with conflicts. Applied patch to 'src/backend/utils/activity/pgstat_lock.c' with conflicts. Applied patch to 'src/backend/utils/adt/pgstatfuncs.c' with conflicts. Applied patch to 'src/include/catalog/catversion.h' with conflicts. Applied patch to 'src/include/catalog/pg_proc.dat' with conflicts. Applied patch to 'src/include/pgstat.h' with conflicts. Applied patch to 'src/include/storage/lock.h' cleanly. Applied patch to 'src/test/regress/expected/rules.out' cleanly. Applied patch to 'src/test/regress/expected/stats.out' with conflicts. Applied patch to 'src/test/regress/sql/stats.sql' cleanly. U src/backend/storage/lmgr/proc.c U src/backend/utils/activity/pgstat_lock.c U src/backend/utils/adt/pgstatfuncs.c U src/include/catalog/catversion.h U src/include/catalog/pg_proc.dat U src/include/pgstat.h U src/test/regress/expected/stats.out diff --cc src/backend/storage/lmgr/proc.c index 9d6e69175a5,5ca89f9fc45..00000000000 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@@ -1641,10 -1611,10 +1641,14 @@@ ProcSleep(LOCALLOCK *locallock /* Increment the lock statistics counters if done waiting. */ if (myWaitStatus == PROC_WAIT_STATUS_OK) pgstat_count_lock_waits(locallock->tag.lock.locktag_type, ++<<<<<<< ours + (PgStat_Counter) secs * 1000000 + usecs); + + msecs = secs * 1000 + usecs / 1000; + usecs = usecs % 1000; ++======= + locallock->blocker_mode, msecs); ++>>>>>>> theirs if (log_lock_waits) { diff --cc src/backend/utils/activity/pgstat_lock.c index c20c7599683,89c7c7b741e..00000000000 --- a/src/backend/utils/activity/pgstat_lock.c +++ b/src/backend/utils/activity/pgstat_lock.c @@@ -125,14 -132,13 +132,15 @@@ pgstat_lock_snapshot_cb(void * like lock acquisitions. */ void - pgstat_count_lock_fastpath_exceeded(uint8 locktag_type) + pgstat_count_lock_fastpath_exceeded(uint8 locktag_type, LOCKMODE lockmode) { Assert(locktag_type <= LOCKTAG_LAST_TYPE); - PendingLockStats.stats[locktag_type].fastpath_exceeded++; + Assert(lockmode > 0 && lockmode <= MaxLockMode); + PendingLockStats.stats[locktag_type][lockmode].fastpath_exceeded++; have_lockstats = true; pgstat_report_fixed = true; + + pgstat_count_backend_lock_fastpath_exceeded(locktag_type); } /* @@@ -142,13 -152,12 +154,22 @@@ * like lock acquisitions. */ void ++<<<<<<< ours +pgstat_count_lock_waits(uint8 locktag_type, PgStat_Counter usecs) +{ + Assert(locktag_type <= LOCKTAG_LAST_TYPE); + PendingLockStats.stats[locktag_type].waits++; + PendingLockStats.stats[locktag_type].wait_time += usecs; ++======= + pgstat_count_lock_waits(uint8 locktag_type, LOCKMODE lockmode, long msecs) + { + Assert(locktag_type <= LOCKTAG_LAST_TYPE); + Assert(lockmode > 0 && lockmode <= MaxLockMode); + PendingLockStats.stats[locktag_type][lockmode].waits++; + PendingLockStats.stats[locktag_type][lockmode].wait_time += (PgStat_Counter) msecs; ++>>>>>>> theirs have_lockstats = true; pgstat_report_fixed = true; + + pgstat_count_backend_lock_waits(locktag_type, usecs); } diff --cc src/backend/utils/adt/pgstatfuncs.c index 565d0e70768,3c819082f4f..00000000000 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@@ -1737,78 -1737,54 +1737,121 @@@ pg_stat_get_wal(PG_FUNCTION_ARGS wal_stats->stat_reset_timestamp)); } -Datum -pg_stat_get_lock(PG_FUNCTION_ARGS) +/* + * pg_stat_lock_build_tuples + * + * Helper routine for pg_stat_get_lock() and pg_stat_get_backend_lock(), + * filling a result tuplestore with one tuple for each lock type. + */ +static void +pg_stat_lock_build_tuples(ReturnSetInfo *rsinfo, + PgStat_LockEntry *lock_stats, + TimestampTz stat_reset_timestamp) { ++<<<<<<< ours +#define PG_STAT_LOCK_COLS 5 + for (int lcktype = 0; lcktype <= LOCKTAG_LAST_TYPE; lcktype++) + { + Datum values[PG_STAT_LOCK_COLS] = {0}; + bool nulls[PG_STAT_LOCK_COLS] = {0}; + PgStat_LockEntry *lck_stats = &lock_stats[lcktype]; + int i = 0; + + values[i++] = CStringGetTextDatum(LockTagTypeNames[lcktype]); + values[i++] = Int64GetDatum(lck_stats->waits); + values[i++] = Float8GetDatum(pg_stat_us_to_ms(lck_stats->wait_time)); + values[i++] = Int64GetDatum(lck_stats->fastpath_exceeded); + if (stat_reset_timestamp != 0) + values[i] = TimestampTzGetDatum(stat_reset_timestamp); + else + nulls[i] = true; ++======= + #define PG_STAT_LOCK_COLS 6 + ReturnSetInfo *rsinfo; + PgStat_Lock *lock_stats; - Assert(i + 1 == PG_STAT_LOCK_COLS); + InitMaterializedSRF(fcinfo, 0); + rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; - tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls); + lock_stats = pgstat_fetch_stat_lock(); + + for (int lcktype = 0; lcktype <= LOCKTAG_LAST_TYPE; lcktype++) + { + const char *locktypename = LockTagTypeNames[lcktype]; + + for (LOCKMODE mode = 1; mode <= MaxLockMode; mode++) + { + Datum values[PG_STAT_LOCK_COLS] = {0}; + bool nulls[PG_STAT_LOCK_COLS] = {0}; + PgStat_LockEntry *lck_stats = &lock_stats->stats[lcktype][mode]; + int i = 0; + + /* + * Skip cells with no recorded activity to keep the view + * sparse. Combinations of (locktype, mode) that never occur + * in practice (e.g. AccessExclusiveLock on transactionid) + * would otherwise appear as noise rows. + */ + if (lck_stats->waits == 0 && + lck_stats->wait_time == 0 && + lck_stats->fastpath_exceeded == 0) + continue; ++>>>>>>> theirs + + values[i++] = CStringGetTextDatum(locktypename); + values[i++] = CStringGetTextDatum(GetLockmodeName(DEFAULT_LOCKMETHOD, + mode)); + values[i++] = Int64GetDatum(lck_stats->waits); + values[i++] = Int64GetDatum(lck_stats->wait_time); + values[i++] = Int64GetDatum(lck_stats->fastpath_exceeded); + values[i] = TimestampTzGetDatum(lock_stats->stat_reset_timestamp); + + Assert(i + 1 == PG_STAT_LOCK_COLS); + + tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, + values, nulls); + } } +} + +Datum +pg_stat_get_lock(PG_FUNCTION_ARGS) +{ + ReturnSetInfo *rsinfo; + PgStat_Lock *lock_stats; + + InitMaterializedSRF(fcinfo, 0); + rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; + + lock_stats = pgstat_fetch_stat_lock(); + + pg_stat_lock_build_tuples(rsinfo, lock_stats->stats, + lock_stats->stat_reset_timestamp); + + return (Datum) 0; +} + +/* + * Returns lock statistics for a backend with given PID. + */ +Datum +pg_stat_get_backend_lock(PG_FUNCTION_ARGS) +{ + int pid; + ReturnSetInfo *rsinfo; + PgStat_Backend *backend_stats; + + InitMaterializedSRF(fcinfo, 0); + rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; + + pid = PG_GETARG_INT32(0); + backend_stats = pgstat_fetch_stat_backend_by_pid(pid, NULL); + + if (!backend_stats) + return (Datum) 0; + + pg_stat_lock_build_tuples(rsinfo, backend_stats->lock_stats.stats, + backend_stats->stat_reset_timestamp); return (Datum) 0; } diff --cc src/include/catalog/catversion.h index f20ea73ed39,8ed38a7746a..00000000000 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@@ -57,6 -57,6 +57,10 @@@ */ /* yyyymmddN */ ++<<<<<<< ours +#define CATALOG_VERSION_NO 202607273 ++======= + #define CATALOG_VERSION_NO 202606131 ++>>>>>>> theirs #endif diff --cc src/include/catalog/pg_proc.dat index f8a021987b5,43aa5777395..00000000000 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@@ -6058,12 -6061,12 +6058,18 @@@ proargnames => '{backend_type,object,context,reads,read_bytes,read_time,writes,write_bytes,write_time,writebacks,writeback_time,extends,extend_bytes,extend_time,hits,evictions,reuses,fsyncs,fsync_time,stats_reset}', prosrc => 'pg_stat_get_io' }, - { oid => '6509', descr => 'statistics: per lock type statistics', - proname => 'pg_stat_get_lock', prorows => '10', proretset => 't', + { oid => '6509', descr => 'statistics: per (lock type, blocker mode) statistics', + proname => 'pg_stat_get_lock', prorows => '40', proretset => 't', provolatile => 'v', proparallel => 'r', prorettype => 'record', ++<<<<<<< ours + proargtypes => '', proallargtypes => '{text,int8,float8,int8,timestamptz}', + proargmodes => '{o,o,o,o,o}', + proargnames => '{locktype,waits,wait_time,fastpath_exceeded,stats_reset}', ++======= + proargtypes => '', proallargtypes => '{text,text,int8,int8,int8,timestamptz}', + proargmodes => '{o,o,o,o,o,o}', + proargnames => '{locktype,mode,waits,wait_time,fastpath_exceeded,stats_reset}', ++>>>>>>> theirs prosrc => 'pg_stat_get_lock' }, { oid => '6386', descr => 'statistics: backend IO statistics', diff --cc src/include/pgstat.h index 58a44857f13,2e21d03fbeb..00000000000 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@@ -649,9 -643,8 +655,14 @@@ extern bool pgstat_tracks_io_op(Backend */ extern void pgstat_lock_flush(bool nowait); ++<<<<<<< ours +extern void pgstat_count_lock_fastpath_exceeded(uint8 locktag_type); +extern void pgstat_count_lock_waits(uint8 locktag_type, + PgStat_Counter usecs); ++======= + extern void pgstat_count_lock_fastpath_exceeded(uint8 locktag_type, LOCKMODE lockmode); + extern void pgstat_count_lock_waits(uint8 locktag_type, LOCKMODE lockmode, long msecs); ++>>>>>>> theirs extern PgStat_Lock *pgstat_fetch_stat_lock(void); /* diff --cc src/test/regress/expected/stats.out index e230356de13,fe4644e2dee..00000000000 --- a/src/test/regress/expected/stats.out +++ b/src/test/regress/expected/stats.out @@@ -2034,11 -2018,8 +2034,16 @@@ BEGI END LOOP; END; $$; ++<<<<<<< ours +SELECT fastpath_exceeded AS fastpath_exceeded_before FROM pg_stat_lock WHERE locktype = 'relation' \gset +-- Test pg_stat_get_backend_lock() +SELECT fastpath_exceeded AS backend_fastpath_exceeded_before + FROM pg_stat_get_backend_lock(pg_backend_pid()) + WHERE locktype = 'relation' \gset ++======= + SELECT COALESCE(sum(fastpath_exceeded), 0) AS fastpath_exceeded_before + FROM pg_stat_lock WHERE locktype = 'relation' \gset ++>>>>>>> theirs -- Needs a lock on each partition SELECT count(*) FROM part_test; count