Skip to content

Commit 9eb4571

Browse files
committed
Complete Insert Exec Implementation
1 parent 86fdcaf commit 9eb4571

15 files changed

Lines changed: 3261 additions & 121 deletions

File tree

.github/scripts/scan-warnings.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ if [[ "$SNAPSHOT_ACTIVE_COUNT" -ne 44 ]]; then
4949
ERROR_FOUND=true
5050
fi
5151

52-
if [[ "$LEAK_COUNT" -ne 416 ]]; then
53-
echo "Error: Expected 416 leak warnings, but found $LEAK_COUNT"
52+
if [[ "$LEAK_COUNT" -ne 29 ]]; then
53+
echo "Error: Expected 29 leak warnings, but found $LEAK_COUNT"
5454
ERROR_FOUND=true
5555
fi
5656

contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2730,20 +2730,34 @@ StatementEnd_Internal(PLtsql_execstate *estate, PLtsql_stmt *stmt, bool error)
27302730
* is inside the procedure of an INSERT-EXEC,
27312731
* or if the INSERT itself is an INSERT-EXEC
27322732
* and it just returned error.
2733+
*
2734+
* INSERT EXEC detection covers both paths: the
2735+
* new path uses the global context
2736+
* (pltsql_insert_exec_active), the legacy path
2737+
* uses the per-estate flag (estate->insert_exec).
27332738
*/
2734-
row_count_valid = !estate->insert_exec &&
2739+
row_count_valid =
2740+
!(estate->insert_exec ||
2741+
(pltsql_plugin_handler_ptr->pltsql_insert_exec_active &&
2742+
pltsql_plugin_handler_ptr->pltsql_insert_exec_active())) &&
27352743
!(markErrorFlag &&
27362744
((PLtsql_stmt_execsql *) stmt)->insert_exec);
27372745
}
27382746
else if (plansource->commandTag == CMDTAG_UPDATE)
27392747
{
27402748
command_type = TDS_CMD_UPDATE;
2741-
row_count_valid = !estate->insert_exec;
2749+
row_count_valid =
2750+
!(estate->insert_exec ||
2751+
(pltsql_plugin_handler_ptr->pltsql_insert_exec_active &&
2752+
pltsql_plugin_handler_ptr->pltsql_insert_exec_active()));
27422753
}
27432754
else if (plansource->commandTag == CMDTAG_DELETE)
27442755
{
27452756
command_type = TDS_CMD_DELETE;
2746-
row_count_valid = !estate->insert_exec;
2757+
row_count_valid =
2758+
!(estate->insert_exec ||
2759+
(pltsql_plugin_handler_ptr->pltsql_insert_exec_active &&
2760+
pltsql_plugin_handler_ptr->pltsql_insert_exec_active()));
27472761
}
27482762

27492763
/*
@@ -2753,7 +2767,10 @@ StatementEnd_Internal(PLtsql_execstate *estate, PLtsql_stmt *stmt, bool error)
27532767
else if (plansource->commandTag == CMDTAG_SELECT)
27542768
{
27552769
command_type = TDS_CMD_SELECT;
2756-
row_count_valid = !estate->insert_exec;
2770+
row_count_valid =
2771+
!(estate->insert_exec ||
2772+
(pltsql_plugin_handler_ptr->pltsql_insert_exec_active &&
2773+
pltsql_plugin_handler_ptr->pltsql_insert_exec_active()));
27572774
}
27582775
}
27592776
}
@@ -2776,6 +2793,27 @@ StatementEnd_Internal(PLtsql_execstate *estate, PLtsql_stmt *stmt, bool error)
27762793
{
27772794
is_proc = true;
27782795
command_type = TDS_CMD_EXECUTE;
2796+
/*
2797+
* For INSERT EXEC, report the row count set in
2798+
* flush_insert_exec_temp_table(). Suppress it when an error is
2799+
* pending: the rows are rolled back, no count is sent to the
2800+
* client, and a counted DONE left pending here would otherwise
2801+
* carry a stale count into the following error DONE token.
2802+
*/
2803+
if (!markErrorFlag &&
2804+
stmt->cmd_type == PLTSQL_STMT_EXEC &&
2805+
((PLtsql_stmt_exec *) stmt)->insert_exec != NULL)
2806+
{
2807+
command_type = TDS_CMD_INSERT;
2808+
row_count_valid = true;
2809+
}
2810+
else if (!markErrorFlag &&
2811+
stmt->cmd_type == PLTSQL_STMT_EXEC_BATCH &&
2812+
((PLtsql_stmt_exec_batch *) stmt)->insert_exec != NULL)
2813+
{
2814+
command_type = TDS_CMD_INSERT;
2815+
row_count_valid = true;
2816+
}
27792817
}
27802818
break;
27812819
default:

contrib/babelfishpg_tsql/src/guc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ bool pltsql_disable_batch_auto_commit = false;
5959
bool pltsql_disable_internal_savepoint = false;
6060
bool pltsql_disable_txn_in_triggers = false;
6161
bool pltsql_recursive_triggers = false;
62-
bool pltsql_enable_new_insert_exec = false;
62+
bool pltsql_enable_new_insert_exec = true;
6363
bool pltsql_noexec = false;
6464
bool pltsql_showplan_all = false;
6565
bool pltsql_showplan_text = false;
@@ -957,7 +957,7 @@ define_custom_variables(void)
957957
gettext_noop("Enables INSERT...EXEC redesign code path"),
958958
NULL,
959959
&pltsql_enable_new_insert_exec,
960-
false,
960+
true,
961961
PGC_SUSET,
962962
GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_DISALLOW_IN_AUTO_FILE,
963963
NULL, NULL, NULL);

contrib/babelfishpg_tsql/src/hooks.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3612,6 +3612,17 @@ bbf_object_access_hook(ObjectAccessType access, Oid classId, Oid objectId, int s
36123612
/* Call view dependency handling function */
36133613
handle_bbf_view_binding_on_object_drop(&obj, false);
36143614
}
3615+
3616+
/*
3617+
* Detect DROP of the INSERT EXEC target table.
3618+
* If the executed procedure drops the target table, we need to fail
3619+
* the INSERT EXEC to prevent errors during flush.
3620+
*/
3621+
if (OidIsValid(insert_exec_ctx.target_rel_oid) &&
3622+
objectId == insert_exec_ctx.target_rel_oid)
3623+
{
3624+
insert_exec_ctx.is_target_relation_modified = true;
3625+
}
36153626
}
36163627
if (access == OAT_DROP && classId == ProcedureRelationId)
36173628
{

contrib/babelfishpg_tsql/src/iterative_exec.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1333,6 +1333,7 @@ dispatch_stmt_handle_error(PLtsql_execstate *estate,
13331333
if (!pltsql_implicit_transactions &&
13341334
is_batch_command(stmt) &&
13351335
!is_part_of_pltsql_trigger(estate) &&
1336+
!pltsql_insert_exec_active() &&
13361337
before_tran_count != NestedTranCount)
13371338
ereport(ERROR,
13381339
(errcode(ERRCODE_T_R_INTEGRITY_CONSTRAINT_VIOLATION),
@@ -1370,7 +1371,7 @@ dispatch_stmt_handle_error(PLtsql_execstate *estate,
13701371
}
13711372
else if (!IsTransactionBlockActive())
13721373
{
1373-
if (is_part_of_pltsql_trycatch_block(estate))
1374+
if (is_part_of_pltsql_trycatch_block(estate) && !pltsql_insert_exec_active())
13741375
{
13751376
HOLD_INTERRUPTS();
13761377
elog(DEBUG1, "TSQL TXN PG semantics : Rollback current transaction");
@@ -1603,6 +1604,21 @@ exec_stmt_iterative(PLtsql_execstate *estate, ExecCodes *exec_codes, ExecConfig_
16031604
estate->cur_error->severity = exec_state_call_stack->error_data.error_severity;
16041605
estate->cur_error->state = exec_state_call_stack->error_data.error_state;
16051606

1607+
/*
1608+
* If a TRY-CATCH is inside the executed procedure, INSERT
1609+
* EXEC is still in progress. Re-throw column mismatch errors
1610+
* to roll back all rows. Other errors (e.g., division by
1611+
* zero) are caught by TRY-CATCH, preserving rows inserted
1612+
* before the error.
1613+
*/
1614+
if (!pltsql_insert_exec_error_at_trycatch_level() &&
1615+
pltsql_insert_exec_active())
1616+
{
1617+
if (estate->cur_error->error != NULL &&
1618+
estate->cur_error->error->sqlerrcode == ERRCODE_DATATYPE_MISMATCH)
1619+
ReThrowError(estate->cur_error->error);
1620+
}
1621+
16061622
/* Goto error handling blocks */
16071623
*pc = err_handler_pc - 1; /* same as how goto handles PC */
16081624

0 commit comments

Comments
 (0)