Thread

  1. [PATCH v2 2/2] fixups

    Álvaro Herrera <alvherre@kurilemu.de> — 2026-07-07T16:35:28Z

    ---
     src/backend/commands/repack.c | 54 ++++++++++++++++++++++-------------
     1 file changed, 34 insertions(+), 20 deletions(-)
    
    diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c
    index 2879c8af574..fcc401ccdb9 100644
    --- a/src/backend/commands/repack.c
    +++ b/src/backend/commands/repack.c
    @@ -2152,6 +2152,10 @@ get_tables_to_repack(RepackCommand cmd, bool usingindex, MemoryContext permcxt)
     
     		/*
     		 * For USING INDEX, scan pg_index to find those with indisclustered.
    +		 *
    +		 * Note we don't obtain lock of any kind on the index, which means the
    +		 * index or its owning table could be gone or change at any point.  We
    +		 * have to be extra careful when examining catalog state for them.
     		 */
     		catalog = table_open(IndexRelationId, AccessShareLock);
     		ScanKeyInit(&entry,
    @@ -2169,7 +2173,7 @@ get_tables_to_repack(RepackCommand cmd, bool usingindex, MemoryContext permcxt)
     
     			index = (Form_pg_index) GETSTRUCT(tuple);
     
    -			classtup = SearchSysCache1(RELOID, ObjectIdGetDatum(index->indrelid));
    +			classtup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(index->indrelid));
     			if (!HeapTupleIsValid(classtup))
     				continue;
     			classForm = (Form_pg_class) GETSTRUCT(classtup);
    @@ -2178,11 +2182,11 @@ get_tables_to_repack(RepackCommand cmd, bool usingindex, MemoryContext permcxt)
     			if (classForm->relpersistence == RELPERSISTENCE_TEMP &&
     				!isTempOrTempToastNamespace(classForm->relnamespace))
     			{
    -				ReleaseSysCache(classtup);
    +				heap_freetuple(classtup);
     				continue;
     			}
     
    -			ReleaseSysCache(classtup);
    +			heap_freetuple(classtup);
     
     			/* noisily skip rels which the user can't process */
     			if (!repack_is_permitted_for_relation(cmd, index->indrelid,
    @@ -2274,7 +2278,9 @@ get_tables_to_repack_partitioned(RepackCommand cmd, Oid relid,
     			if (get_rel_relkind(child_oid) != RELKIND_INDEX)
     				continue;
     
    -			table_oid = IndexGetRelation(child_oid, false);
    +			table_oid = IndexGetRelation(child_oid, true);
    +			if (!OidIsValid(table_oid))
    +				continue;
     			index_oid = child_oid;
     		}
     		else
    @@ -2309,33 +2315,41 @@ get_tables_to_repack_partitioned(RepackCommand cmd, Oid relid,
     
     
     /*
    - * Return whether userid has privileges to REPACK relid.  If not, this
    - * function emits a WARNING.
    + * Return whether userid has privileges to execute REPACK on relid.
    + *
    + * Caller may not have a lock on the relation, so it could have been
    + * dropped concurrently.  In that case, silently return false.
    + *
    + * If the relation does exist but the user doesn't have the required
    + * privs, emit a WARNING and return false.  Otherwise, return true.
      */
     static bool
     repack_is_permitted_for_relation(RepackCommand cmd, Oid relid, Oid userid)
     {
     	bool		is_missing = false;
    +	AclResult	result;
    +	char	   *relname;
     
     	Assert(cmd == REPACK_COMMAND_CLUSTER || cmd == REPACK_COMMAND_REPACK);
     
    -	if (pg_class_aclcheck_ext(relid, userid, ACL_MAINTAIN, &is_missing) == ACLCHECK_OK)
    +	result = pg_class_aclcheck_ext(relid, userid, ACL_MAINTAIN, &is_missing);
    +	if (is_missing)
    +		return false;
    +
    +	if (result == ACLCHECK_OK)
     		return true;
     
    -	/* Report a warning if the relation still exists. */
    -	if (!is_missing)
    +	/*
    +	 * The relation can also be dropped after we tested its ACL and before we
    +	 * read its relname, so be careful.
    +	 */
    +	relname = get_rel_name(relid);
    +	if (relname != NULL)
     	{
    -		char	   *relname;
    -
    -		relname = get_rel_name(relid);
    -		if (relname != NULL)
    -		{
    -			ereport(WARNING,
    -					errmsg("permission denied to execute %s on \"%s\", skipping it",
    -						   RepackCommandAsString(cmd), relname));
    -
    -			pfree(relname);
    -		}
    +		ereport(WARNING,
    +				errmsg("permission denied to execute %s on \"%s\", skipping it",
    +					   RepackCommandAsString(cmd), relname));
    +		pfree(relname);
     	}
     
     	return false;
    -- 
    2.47.3
    
    
    --op6mnexl7cn72cto--