Commit 112b039
committed
Fix INSERT EXEC error 556: Detect schema changes during execution
Problem:
SQL Server raises error 556 ('INSERT EXEC failed because the stored procedure
altered the schema of the target table') when a procedure executed via INSERT
EXEC modifies the target table's schema (e.g., ALTER TABLE ADD COLUMN).
Babelfish was not detecting this scenario.
Previous Approaches (Failed):
1. Holding target table open with table_open() - Fixed 556_1 test but caused
'relcache reference not owned by resource owner' errors in upgrade tests
because Relation pointers cannot be held across subtransaction boundaries.
2. Using locks only with LockRelationOid() - Fixed upgrade tests but broke
556_1 because CheckTableNotInUse() only checks reference count, not locks.
Solution (Schema Signature Approach):
Instead of holding the Relation pointer open, we now:
1. Capture the target table's 'schema signature' at INSERT EXEC start:
- Column count (natts)
- Column type OIDs (atttypids)
- Column type modifiers (atttypmods)
2. Acquire RowExclusiveLock on the target table (released at transaction end)
3. Before flushing buffered data to the target, verify the schema signature
hasn't changed
4. If schema changed, raise error 556 with the appropriate SQL Server message
Major Version Upgrade Handling:
In major version upgrade scenarios, table OIDs may change (tables are recreated
with different OIDs). The schema verification and lock release functions now
wrap table_open/UnlockRelationOid calls in PG_TRY blocks to gracefully handle
stale OIDs - if the relation cannot be opened, we skip the schema check and
let the actual INSERT validate the data.
This approach:
- Detects ALTER TABLE operations that change column count or types
- Avoids holding Relation pointers across subtransaction boundaries
- Works correctly with upgrade tests (no relcache reference issues)
- Handles stale OIDs gracefully in major version upgrade scenarios
- Properly handles temp tables and table variables (skips schema capture)
Implementation Details:
- Added InsertExecSchemaSignature struct to store column metadata
- Added pltsql_insert_exec_verify_schema() to check schema before flush
- Modified pltsql_insert_exec_open_target_table() to capture schema signature
- Modified pltsql_insert_exec_close_target_table() to free schema signature
- Modified flush_insert_exec_temp_table() to call verify and raise error 556
- Added error mapping for the new error message to map to SQL Server error 556
- Added PG_TRY/PG_CATCH blocks to handle stale OIDs in upgrade scenarios
Files Changed:
- contrib/babelfishpg_tsql/src/pl_exec-2.c: Schema signature implementation
- contrib/babelfishpg_tsql/src/pltsql.h: Added pltsql_insert_exec_verify_schema()
- contrib/babelfishpg_tds/error_mapping.txt: Added error 556 mapping
- test/JDBC/expected/TestErrorHelperFunctions.out: Updated expected output
- test/JDBC/expected/TestErrorHelperFunctionsUpgrade-vu-verify.out: Updated
Tests Verified:
- 556_1: Passed (schema change detection)
- BABEL-1944: Passed (upgrade test - no relcache issues)
- BABEL-INSERT-EXEC: Passed (general INSERT EXEC functionality)
- BABEL-INSERT-EXECUTE: Passed (INSERT EXECUTE functionality)
- TestErrorHelperFunctions: Passed (error mapping validation)1 parent 2d9d515 commit 112b039
File tree
5 files changed
+287
-40
lines changed- contrib
- babelfishpg_tds
- babelfishpg_tsql/src
- test/JDBC/expected
5 files changed
+287
-40
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
188 | 188 | | |
189 | 189 | | |
190 | 190 | | |
| 191 | + | |
191 | 192 | | |
0 commit comments