@@ -4818,6 +4818,10 @@ public MutationState addColumn(PTable table, List<ColumnDef> origColumnDefs,
48184818 Set <String > acquiredColumnMutexSet = Sets .newHashSetWithExpectedSize (3 );
48194819 boolean acquiredBaseTableMutex = false ;
48204820 boolean acquiredTransformLock = false ;
4821+ // Tracks the post-re-check fresh table view; used as the source-of-truth for transform-decision
4822+ // sites (incrementTableSeqNum + addTransform). Defaults to {@code table} when no transform is
4823+ // needed or when the lock was already held by a parent frame (no second re-check happens).
4824+ PTable freshTable = table ;
48214825 try {
48224826 connection .setAutoCommit (false );
48234827 List <ColumnDef > columnDefs ;
@@ -4959,8 +4963,9 @@ public MutationState addColumn(PTable table, List<ColumnDef> origColumnDefs,
49594963 // Re-check under lock with fresh metadata: a concurrent transform-triggering ALTER
49604964 // may have committed between our first checkIsTransformNeeded and the lock acquire.
49614965 // If so, the transform we observed is stale — drop through and treat as no-op.
4962- PTable freshTable =
4963- connection .getTableNoCache (SchemaUtil .getTableName (schemaName , tableName ));
4966+ // Capture freshTable so downstream transform-decision sites (incrementTableSeqNum,
4967+ // addTransform) see the post-re-check view rather than the stale {@code table}.
4968+ freshTable = connection .getTableNoCache (SchemaUtil .getTableName (schemaName , tableName ));
49644969 isTransformNeeded = TransformClient .checkIsTransformNeeded (metaProperties , schemaName ,
49654970 freshTable , tableName , null , tenantIdToUse , connection );
49664971 }
@@ -5201,7 +5206,7 @@ public MutationState addColumn(PTable table, List<ColumnDef> origColumnDefs,
52015206 long seqNum = 0 ;
52025207 if (changingPhoenixTableProperty || columnDefs .size () > 0 ) {
52035208 seqNum =
5204- incrementTableSeqNum (table , tableType , columnDefs .size (), metaPropertiesEvaluated );
5209+ incrementTableSeqNum (freshTable , tableType , columnDefs .size (), metaPropertiesEvaluated );
52055210
52065211 tableMetaData
52075212 .addAll (connection .getMutationState ().toMutations (timeStamp ).next ().getSecond ());
@@ -5211,8 +5216,8 @@ public MutationState addColumn(PTable table, List<ColumnDef> origColumnDefs,
52115216 PTable transformingNewTable = null ;
52125217 if (isTransformNeeded ) {
52135218 try {
5214- transformingNewTable = TransformClient .addTransform (connection , tenantIdToUse , table ,
5215- metaProperties , seqNum , PTable .TransformType .METADATA_TRANSFORM );
5219+ transformingNewTable = TransformClient .addTransform (connection , tenantIdToUse ,
5220+ freshTable , metaProperties , seqNum , PTable .TransformType .METADATA_TRANSFORM );
52165221 } catch (SQLException ex ) {
52175222 connection .rollback ();
52185223 throw ex ;
@@ -6001,9 +6006,6 @@ public MutationState alterIndex(AlterIndexStatement statement) throws SQLExcepti
60016006
60026007 boolean isTransformNeeded = TransformClient .checkIsTransformNeeded (metaProperties , schemaName ,
60036008 table , indexName , dataTableName , tenantId , connection );
6004- MetaPropertiesEvaluated metaPropertiesEvaluated = new MetaPropertiesEvaluated ();
6005- boolean changingPhoenixTableProperty = evaluateStmtProperties (metaProperties ,
6006- metaPropertiesEvaluated , table , schemaName , tableName , new MutableBoolean (false ));
60076009
60086010 PIndexState newIndexState = statement .getIndexState ();
60096011 IndexConsistency newIndexConsistency = statement .getIndexConsistency ();
@@ -6050,6 +6052,37 @@ public MutationState alterIndex(AlterIndexStatement statement) throws SQLExcepti
60506052 connection .setAutoCommit (false );
60516053 // Confirm index table is valid and up-to-date
60526054 TableRef indexRef = FromCompiler .getResolver (statement , connection ).getTables ().get (0 );
6055+
6056+ // If the statement is a transform-triggering ALTER INDEX, acquire the transform lock and
6057+ // re-check freshness under the lock BEFORE we commit any index-state UPSERT. Otherwise a
6058+ // contending caller would see (or leave behind) a half-committed BUILDING state if the
6059+ // lock acquire failed below.
6060+ PTable freshTable = table ;
6061+ boolean stillTransformNeeded = false ;
6062+ if (isTransformNeeded ) {
6063+ if (indexRef .getTable ().getViewIndexId () != null ) {
6064+ throw new SQLExceptionInfo .Builder (SQLExceptionCode .CANNOT_TRANSFORM_LOCAL_OR_VIEW_INDEX )
6065+ .setSchemaName (schemaName ).setTableName (indexName ).build ().buildException ();
6066+ }
6067+ acquiredTransformLock =
6068+ connection .getQueryServices ().acquireTransformLock (tenantId , schemaName , tableName );
6069+ if (!acquiredTransformLock ) {
6070+ throw new SQLExceptionInfo .Builder (
6071+ SQLExceptionCode .CANNOT_MODIFY_TABLE_WITH_TRANSFORM_IN_PROGRESS )
6072+ .setSchemaName (schemaName ).setTableName (tableName ).build ().buildException ();
6073+ }
6074+ // Re-check under lock with fresh metadata: a concurrent transform-triggering ALTER may
6075+ // have committed between our first checkIsTransformNeeded and the lock acquire. If the
6076+ // observed transform is no longer needed, drop through and treat as no-op.
6077+ freshTable = connection .getTableNoCache (SchemaUtil .getTableName (schemaName , tableName ));
6078+ stillTransformNeeded = TransformClient .checkIsTransformNeeded (metaProperties , schemaName ,
6079+ freshTable , indexName , dataTableName , tenantId , connection );
6080+ }
6081+
6082+ MetaPropertiesEvaluated metaPropertiesEvaluated = new MetaPropertiesEvaluated ();
6083+ boolean changingPhoenixTableProperty = evaluateStmtProperties (metaProperties ,
6084+ metaPropertiesEvaluated , freshTable , schemaName , tableName , new MutableBoolean (false ));
6085+
60536086 try (PreparedStatement tableUpsert = connection .prepareStatement (
60546087 newIndexState == PIndexState .ACTIVE ? UPDATE_INDEX_STATE_TO_ACTIVE : UPDATE_INDEX_STATE )) {
60556088 tableUpsert .setString (1 ,
@@ -6069,14 +6102,15 @@ public MutationState alterIndex(AlterIndexStatement statement) throws SQLExcepti
60696102 connection .rollback ();
60706103
60716104 if (changingPhoenixTableProperty ) {
6072- seqNum = incrementTableSeqNum (table , statement .getTableType (), 0 , metaPropertiesEvaluated );
6105+ seqNum =
6106+ incrementTableSeqNum (freshTable , statement .getTableType (), 0 , metaPropertiesEvaluated );
60736107 tableMetadata
60746108 .addAll (connection .getMutationState ().toMutations (timeStamp ).next ().getSecond ());
60756109 connection .rollback ();
60766110 }
60776111
60786112 MetaDataMutationResult result = connection .getQueryServices ().updateIndexState (tableMetadata ,
6079- dataTableName , properties , table );
6113+ dataTableName , properties , freshTable );
60806114
60816115 try {
60826116 MutationCode code = result .getMutationCode ();
@@ -6090,34 +6124,13 @@ public MutationState alterIndex(AlterIndexStatement statement) throws SQLExcepti
60906124 .setSchemaName (schemaName ).setTableName (indexName ).build ().buildException ();
60916125 }
60926126
6093- if (isTransformNeeded ) {
6094- if (indexRef .getTable ().getViewIndexId () != null ) {
6095- throw new SQLExceptionInfo .Builder (
6096- SQLExceptionCode .CANNOT_TRANSFORM_LOCAL_OR_VIEW_INDEX ).setSchemaName (schemaName )
6097- .setTableName (indexName ).build ().buildException ();
6098- }
6099- acquiredTransformLock =
6100- connection .getQueryServices ().acquireTransformLock (tenantId , schemaName , tableName );
6101- if (!acquiredTransformLock ) {
6102- throw new SQLExceptionInfo .Builder (
6103- SQLExceptionCode .CANNOT_MODIFY_TABLE_WITH_TRANSFORM_IN_PROGRESS )
6104- .setSchemaName (schemaName ).setTableName (tableName ).build ().buildException ();
6105- }
6106- // Re-check under lock with fresh metadata: a concurrent transform-triggering ALTER may
6107- // have committed between our first checkIsTransformNeeded and the lock acquire. If the
6108- // observed transform is no longer needed, drop through and treat as no-op.
6109- PTable freshTable =
6110- connection .getTableNoCache (SchemaUtil .getTableName (schemaName , tableName ));
6111- boolean stillTransformNeeded = TransformClient .checkIsTransformNeeded (metaProperties ,
6112- schemaName , freshTable , indexName , dataTableName , tenantId , connection );
6113- if (stillTransformNeeded ) {
6114- try {
6115- TransformClient .addTransform (connection , tenantId , table , metaProperties , seqNum ,
6116- PTable .TransformType .METADATA_TRANSFORM );
6117- } catch (SQLException ex ) {
6118- connection .rollback ();
6119- throw ex ;
6120- }
6127+ if (isTransformNeeded && stillTransformNeeded ) {
6128+ try {
6129+ TransformClient .addTransform (connection , tenantId , freshTable , metaProperties , seqNum ,
6130+ PTable .TransformType .METADATA_TRANSFORM );
6131+ } catch (SQLException ex ) {
6132+ connection .rollback ();
6133+ throw ex ;
61216134 }
61226135 }
61236136
0 commit comments