|
13 | 13 | */
|
14 | 14 | #include "postgres.h"
|
15 | 15 |
|
| 16 | +#include "access/heapam.h" |
16 | 17 | #include "access/htup_details.h"
|
17 | 18 | #include "access/table.h"
|
18 | 19 | #include "access/xact.h"
|
@@ -943,18 +944,45 @@ EventTriggerOnLogin(void)
|
943 | 944 | Relation pg_db = table_open(DatabaseRelationId, RowExclusiveLock);
|
944 | 945 | HeapTuple tuple;
|
945 | 946 | Form_pg_database db;
|
| 947 | + ScanKeyData key[1]; |
| 948 | + SysScanDesc scan; |
946 | 949 |
|
947 |
| - tuple = SearchSysCacheCopy1(DATABASEOID, |
948 |
| - ObjectIdGetDatum(MyDatabaseId)); |
| 950 | + /* |
| 951 | + * Get the pg_database tuple to scribble on. Note that this does |
| 952 | + * not directly rely on the syscache to avoid issues with |
| 953 | + * flattened toast values for the in-place update. |
| 954 | + */ |
| 955 | + ScanKeyInit(&key[0], |
| 956 | + Anum_pg_database_oid, |
| 957 | + BTEqualStrategyNumber, F_OIDEQ, |
| 958 | + ObjectIdGetDatum(MyDatabaseId)); |
| 959 | + |
| 960 | + scan = systable_beginscan(pg_db, DatabaseOidIndexId, true, |
| 961 | + NULL, 1, key); |
| 962 | + tuple = systable_getnext(scan); |
| 963 | + tuple = heap_copytuple(tuple); |
| 964 | + systable_endscan(scan); |
949 | 965 |
|
950 | 966 | if (!HeapTupleIsValid(tuple))
|
951 |
| - elog(ERROR, "cache lookup failed for database %u", MyDatabaseId); |
| 967 | + elog(ERROR, "could not find tuple for database %u", MyDatabaseId); |
952 | 968 |
|
953 | 969 | db = (Form_pg_database) GETSTRUCT(tuple);
|
954 | 970 | if (db->dathasloginevt)
|
955 | 971 | {
|
956 | 972 | db->dathasloginevt = false;
|
957 |
| - CatalogTupleUpdate(pg_db, &tuple->t_self, tuple); |
| 973 | + |
| 974 | + /* |
| 975 | + * Do an "in place" update of the pg_database tuple. Doing |
| 976 | + * this instead of regular updates serves two purposes. First, |
| 977 | + * that avoids possible waiting on the row-level lock. Second, |
| 978 | + * that avoids dealing with TOAST. |
| 979 | + * |
| 980 | + * It's known that changes made by heap_inplace_update() may |
| 981 | + * be lost due to concurrent normal updates. However, we are |
| 982 | + * OK with that. The subsequent connections will still have a |
| 983 | + * chance to set "dathasloginevt" to false. |
| 984 | + */ |
| 985 | + heap_inplace_update(pg_db, tuple); |
958 | 986 | }
|
959 | 987 | table_close(pg_db, RowExclusiveLock);
|
960 | 988 | heap_freetuple(tuple);
|
|
0 commit comments