@@ -223,11 +223,11 @@ void
223223pltsql_set_insert_exec_context_info (const char * target_table )
224224{
225225 Assert (insert_exec_ctx == NULL );
226- insert_exec_ctx = MemoryContextAllocZero (TopTransactionContext ,
226+ insert_exec_ctx = MemoryContextAllocZero (TopMemoryContext ,
227227 sizeof (InsertExecContext ));
228228
229229 insert_exec_ctx -> target_table = target_table
230- ? MemoryContextStrdup (TopTransactionContext , target_table )
230+ ? MemoryContextStrdup (TopMemoryContext , target_table )
231231 : NULL ;
232232 /*
233233 * Snapshot the call stack entry at INSERT EXEC start. Comparing this
@@ -531,7 +531,6 @@ flush_insert_exec_temp_table(PLtsql_execstate *estate, const char *target_schema
531531 Relation temp_rel ;
532532 char * qualified_target ;
533533 InlineCodeBlockArgs * flush_args ;
534- PLtsql_execstate * flush_estate_saved ;
535534
536535 if (insert_exec_ctx == NULL )
537536 return ;
@@ -597,19 +596,21 @@ flush_insert_exec_temp_table(PLtsql_execstate *estate, const char *target_schema
597596 */
598597 flush_args = create_args (0 );
599598
600- flush_estate_saved = insert_exec_flush_estate ;
599+ if (insert_exec_flush_estate != NULL )
600+ elog (ERROR , "insert_exec_flush_estate is already set; INSERT EXEC flush must not nest" );
601+
601602 insert_exec_flush_estate = estate ;
602603 PG_TRY ();
603604 {
604605 rc = execute_batch (estate , flush_query .data , flush_args , NULL );
605606 }
606607 PG_CATCH ();
607608 {
608- insert_exec_flush_estate = flush_estate_saved ;
609+ insert_exec_flush_estate = NULL ;
609610 PG_RE_THROW ();
610611 }
611612 PG_END_TRY ();
612- insert_exec_flush_estate = flush_estate_saved ;
613+ insert_exec_flush_estate = NULL ;
613614
614615 pfree (flush_query .data );
615616
@@ -841,6 +842,19 @@ insert_exec_setup(PLtsql_execstate *estate,
841842 (errcode (ERRCODE_PROGRAM_LIMIT_EXCEEDED ),
842843 errmsg ("nested INSERT ... EXECUTE statements are not allowed" )));
843844
845+ /*
846+ * T-SQL does not allow INSERT EXEC inside a function. The parser blocks
847+ * the common cases at CREATE FUNCTION time; this catches anything that
848+ * still reaches runtime (e.g. a table-variable target).
849+ */
850+ if (estate -> func &&
851+ estate -> func -> fn_oid != InvalidOid &&
852+ estate -> func -> fn_prokind == PROKIND_FUNCTION &&
853+ estate -> func -> fn_is_trigger == PLTSQL_NOT_TRIGGER )
854+ ereport (ERROR ,
855+ (errcode (ERRCODE_INVALID_FUNCTION_DEFINITION ),
856+ errmsg ("'INSERT EXEC' cannot be used within a function" )));
857+
844858 /* Build the quoted column list (if any) for temp table creation */
845859 column_list = build_quoted_column_list (info -> columns );
846860
@@ -851,15 +865,9 @@ insert_exec_setup(PLtsql_execstate *estate,
851865 */
852866 if (start_implicit_txn )
853867 {
854- bool in_function = (estate -> func &&
855- estate -> func -> fn_oid != InvalidOid &&
856- estate -> func -> fn_prokind == PROKIND_FUNCTION &&
857- estate -> func -> fn_is_trigger == PLTSQL_NOT_TRIGGER );
858-
859868 if (!pltsql_disable_batch_auto_commit &&
860869 pltsql_support_tsql_transactions () &&
861- !IsTransactionBlockActive () &&
862- !in_function )
870+ !IsTransactionBlockActive ())
863871 {
864872 elog (DEBUG4 , "TSQL TXN Start internal transaction for INSERT EXEC" );
865873 pltsql_start_txn ();
@@ -899,20 +907,7 @@ insert_exec_flush_and_cleanup(PLtsql_execstate *estate, InsertExecInfo *info)
899907 char * column_list = build_quoted_column_list (info -> columns );
900908 const char * flush_schema = (info -> db_name != NULL || info -> schema != NULL ) ? info -> schema : NULL ;
901909
902- PG_TRY ();
903- {
904- /* Flush temp table to target table */
905- flush_insert_exec_temp_table (estate , flush_schema , info -> db_name , column_list );
906- }
907- PG_CATCH ();
908- {
909- /* Free the column list and reset context before re-throwing. */
910- if (column_list != NULL )
911- pfree (column_list );
912- pltsql_insert_exec_reset_all ();
913- PG_RE_THROW ();
914- }
915- PG_END_TRY ();
910+ flush_insert_exec_temp_table (estate , flush_schema , info -> db_name , column_list );
916911
917912 if (column_list != NULL )
918913 pfree (column_list );
0 commit comments