Skip to content

Commit a09245a

Browse files
committed
Fix INSERT EXEC stale OID errors by closing target table before clearing context
During major version upgrade tests, BABEL-1944 was failing with could not open relation with OID errors. The root cause was that error cleanup paths were calling pltsql_clear_insert_exec_context() WITHOUT first calling pltsql_insert_exec_close_target_table(), leaving insert_exec_target_rel_oid set to a stale OID. When a subsequent INSERT EXEC operation tried to use this stale OID, it would fail because the relation no longer existed with that OID (tables get recreated with new OIDs during major version upgrades). Changes: 1. Add early INSERT EXEC context cleanup at the start of error handling (dispatch_stmt_handle_error), before any transaction state checks. This ensures the INSERT EXEC state is cleared regardless of transaction state, preventing stale OID issues. 2. Add pltsql_insert_exec_close_target_table() calls before pltsql_clear_insert_exec_context() in all error cleanup paths: - iterative_exec.c: TRY-CATCH cleanup path - pl_exec-2.c: exec_stmt_try_catch cleanup 3. Simplify the !IsTransactionBlockActive() branch since INSERT EXEC context is now cleaned up earlier. The skip_abort logic now only checks pltsql_insert_exec_in_trycatch() without the nested pltsql_insert_exec_active() check.
1 parent 8f14a6e commit a09245a

File tree

2 files changed

+36
-26
lines changed

2 files changed

+36
-26
lines changed

contrib/babelfishpg_tsql/src/iterative_exec.c

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1490,6 +1490,25 @@ dispatch_stmt_handle_error(PLtsql_execstate *estate,
14901490
edata = CopyErrorData();
14911491
error_mapped = get_tsql_error_code(edata, &last_error);
14921492
exec_set_error(estate, last_error, edata->sqlerrcode, !error_mapped);
1493+
1494+
/*
1495+
* Clean up INSERT EXEC context on error.
1496+
* This must be done early, before any transaction handling, to ensure
1497+
* the INSERT EXEC state is cleared regardless of the transaction state.
1498+
*
1499+
* Without this cleanup, if INSERT EXEC fails inside an explicit transaction
1500+
* (e.g., BEGIN TRAN; INSERT INTO t EXEC proc; where proc does COMMIT without
1501+
* BEGIN TRAN), the INSERT EXEC context remains set. Subsequent queries then
1502+
* see pltsql_insert_exec_active() as true and try to use stale OIDs, causing
1503+
* "could not open relation with OID" errors.
1504+
*/
1505+
if (pltsql_insert_exec_active())
1506+
{
1507+
elog(DEBUG1, "TSQL TXN TSQL semantics : Cleaning up INSERT EXEC context on error");
1508+
pltsql_insert_exec_close_target_table();
1509+
pltsql_clear_insert_exec_context();
1510+
}
1511+
14931512
if (internal_sp_started &&
14941513
before_lxid == MyProc->vxid.lxid &&
14951514
before_subtxn_id == GetCurrentSubTransactionId())
@@ -1515,37 +1534,22 @@ dispatch_stmt_handle_error(PLtsql_execstate *estate,
15151534
* 3. The error will be caught by TRY-CATCH and the transaction
15161535
* state will be handled properly when INSERT EXEC completes
15171536
*
1518-
* IMPORTANT: We only skip the abort if there's a TRY-CATCH that
1519-
* will catch the error. If there's no TRY-CATCH, we should clean
1520-
* up the INSERT EXEC context and let the transaction abort normally.
1521-
* Otherwise, the temp table will be left behind and cause
1522-
* "relation already exists" errors on subsequent INSERT EXEC.
1537+
* NOTE: The INSERT EXEC context is now cleaned up earlier in the
1538+
* error handling path (before the transaction state checks), so
1539+
* pltsql_insert_exec_active() will return false here. We keep
1540+
* the skip_abort logic for TRY-CATCH handling, but the INSERT EXEC
1541+
* cleanup is no longer needed here.
15231542
*/
15241543
bool skip_abort = false;
15251544

15261545
/*
1527-
* Only skip abort for INSERT EXEC if there's a TRY-CATCH that
1528-
* will catch the error. If no TRY-CATCH, clean up INSERT EXEC
1529-
* context and let the transaction abort.
1546+
* Skip abort if there's a TRY-CATCH that will catch the error.
1547+
* The INSERT EXEC context has already been cleaned up earlier.
15301548
*/
1531-
if (pltsql_insert_exec_active())
1549+
if (pltsql_insert_exec_in_trycatch())
15321550
{
1533-
if (pltsql_insert_exec_in_trycatch())
1534-
{
1535-
skip_abort = true;
1536-
elog(DEBUG1, "TSQL TXN TSQL semantics : Skip transaction rollback during INSERT EXEC (TRY-CATCH will handle)");
1537-
}
1538-
else
1539-
{
1540-
/*
1541-
* No TRY-CATCH to catch the error. Clean up INSERT EXEC
1542-
* context so the temp table is dropped when transaction
1543-
* aborts. We just clear the context here - the temp table
1544-
* will be dropped by the transaction abort.
1545-
*/
1546-
elog(DEBUG1, "TSQL TXN TSQL semantics : INSERT EXEC active but no TRY-CATCH, clearing context for cleanup");
1547-
pltsql_clear_insert_exec_context();
1548-
}
1551+
skip_abort = true;
1552+
elog(DEBUG1, "TSQL TXN TSQL semantics : Skip transaction rollback (TRY-CATCH will handle)");
15491553
}
15501554

15511555
if (!skip_abort)
@@ -1791,7 +1795,10 @@ exec_stmt_iterative(PLtsql_execstate *estate, ExecCodes *exec_codes, ExecConfig_
17911795

17921796
elog(DEBUG1, "INSERT-EXEC: Cleaning up after error caught by TRY-CATCH, temp_oid=%u", temp_oid);
17931797

1794-
/* Clear the INSERT EXEC context first */
1798+
/* Close target table and release lock first */
1799+
pltsql_insert_exec_close_target_table();
1800+
1801+
/* Clear the INSERT EXEC context */
17951802
pltsql_clear_insert_exec_context();
17961803

17971804
/* Drop the temp table if it exists */

contrib/babelfishpg_tsql/src/pl_exec-2.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2922,6 +2922,9 @@ exec_stmt_try_catch(PLtsql_execstate *estate, PLtsql_stmt_try_catch *stmt)
29222922
elog(LOG, "INSERT-EXEC TRY-CATCH cleanup: is_stmt_terminating=%d, insert_exec_was_active=%d, temp_oid=%u",
29232923
is_stmt_terminating, insert_exec_was_active, temp_oid);
29242924

2925+
/* Close target table and release lock first */
2926+
pltsql_insert_exec_close_target_table();
2927+
29252928
/* Clear the INSERT EXEC context */
29262929
pltsql_clear_insert_exec_context();
29272930

0 commit comments

Comments
 (0)