If I actively BEGIN a transaction, but fail to ROLLBACK at error, will PG become confused? Suppose I have this application pseudo code (it's actually PHP and communicating with PG with the pg_* functions):
function handle_update_of_foo_table()
{
    BEGIN;
    TRUNCATE TABLE foo;
    
    loop (thousands of times)
    {
        INSERT INTO foo blablabla...;
        
        if (INSERT FAILED)
        {
            ROLLBACK;
            return false;
        }
    }

    COMMIT;
    return true;
}

handle_update_of_foo_table();
UPDATE unrelated_table SET blablabla;

Do I understand things right if I say that, had I not actively remembered to do the &quot;ROLLBACK&quot; before returning, when an INSERT failed for whatever reason, the transaction would have &quot;continued on&quot; to perform the unrelated UPDATE query inside the transaction, and thus, when the script ends right afterwards, it would have auto-rolled back because there had been a BEGIN but no COMMIT, so as far as PG is aware, all of my queries, including the unrelated UPDATE in the end, are part of the same transaction? And thus, the unrelated_table will not be updated in the end, because the entire transaction was auto-rolled back due to not COMMIT?
With me forgetting the ROLLBACK (which I did not forget in the example code, but might very easily do in reality somewhere), it has no way to know what my intentions were since it just sees a series of queries inside an explicitly started &quot;transaction&quot;?
If I have understood this, I think I finally &quot;get&quot; transactions. It only took me twenty years...
The transaction won't be &quot;auto rolled back&quot;, it will be marked as failed, and the only option you have, is to do a rollback.
If you did not run rollback in the function but simply return from it in case of an error, then the UPDATE following the function call would result in &quot;current transaction is aborted, commands ignored until end of transaction block&quot; - so the UPDATE can't be run either (again: only if you omit the rollback in the function in case of an error).

Unrelated to your question, but: your UPDATE will (implicitly) run in a second (different) transaction if your insert succeeds because your function cleanly ends the transaction that was started in there. If you did mean to run insert and update in the same transaction, your code is not going to do that.