PHOENIX-2099 Backward Compatibility - Concurrent modification error on connect
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/39afa9f1 Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/39afa9f1 Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/39afa9f1 Branch: refs/heads/calcite Commit: 39afa9f18cad132a8a5c49b0e2e31671c85a3c7e Parents: 997de5e Author: Samarth <samarth.j...@salesforce.com> Authored: Fri Jul 10 11:04:44 2015 -0700 Committer: Samarth <samarth.j...@salesforce.com> Committed: Fri Jul 10 11:04:44 2015 -0700 ---------------------------------------------------------------------- .../coprocessor/MetaDataEndpointImpl.java | 24 +- .../query/ConnectionQueryServicesImpl.java | 8 +- .../org/apache/phoenix/util/UpgradeUtil.java | 416 ++++++++++--------- phoenix-protocol/src/main/PTable.proto | 1 + 4 files changed, 237 insertions(+), 212 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/39afa9f1/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java index f786768..399d56e 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java @@ -39,7 +39,6 @@ import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.IS_ARRAY_BYTES; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.IS_CONSTANT_BYTES; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.IS_VIEW_REFERENCED_BYTES; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.JAR_PATH_BYTES; -import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.KEY_SEQ_BYTES; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.LINK_TYPE_BYTES; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.MAX_VALUE_BYTES; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.MIN_VALUE_BYTES; @@ -1567,12 +1566,6 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso // We said to drop a table, but found a view or visa versa if (type != expectedType) { return new MetaDataMutationResult(MutationCode.TABLE_NOT_FOUND, EnvironmentEdgeManager.currentTimeMillis(), null); } - if (table.getBaseColumnCount() == 0) { - // If the base column count hasn't been set, then it means that the upgrade - // to 4.5.0 is in progress. Have the client retry the mutation operation. - return new MetaDataMutationResult(MutationCode.CONCURRENT_TABLE_MUTATION, - EnvironmentEdgeManager.currentTimeMillis(), table); - } } result = mutator.updateMutation(table, rowKeyMetaData, tableMetadata, region, invalidateList, locks, clientTimeStamp); @@ -1658,7 +1651,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso } // if there is already a view column with the same name as the base table column we are trying to add - if (existingViewColumn!=null) { + if (existingViewColumn != null) { List<Cell> dataTypes = viewColumnDefinitionPut .get(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES, PhoenixDatabaseMetaData.DATA_TYPE_BYTES); @@ -1684,7 +1677,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso } } // if there is an existing view column that matches the column being added to the base table and if the column being added has a null - // scale or maxLength, we need to explicity do a put to set the scale or maxLength to null (in case the view column has the scale or + // scale or maxLength, we need to explicitly do a put to set the scale or maxLength to null (in case the view column has the scale or // max length set) List<Cell> columnSizes = viewColumnDefinitionPut.get( PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES, @@ -1714,7 +1707,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso } } else { - // if we are adding a column that already exists in the view, no need to updates the base table or view table column count + // if we are adding a column that already exists in the view, no need to update the base table or view table column count numColsAddedToView++; } @@ -1914,9 +1907,14 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso if (type == PTableType.TABLE || type == PTableType.SYSTEM) { TableViewFinderResult childViewsResult = findChildViews(region, tenantId, table, PHYSICAL_TABLE_BYTES); if (childViewsResult.hasViews()) { - // Adding a column is not allowed if the meta-data for child view/s spans over - // more than one region (since the changes cannot be done in a transactional fashion) - if (!childViewsResult.allViewsInSingleRegion()) { + /* + * Adding a column is not allowed if the meta-data for child view/s spans over + * more than one region (since the changes cannot be made in a transactional fashion) + * A base column count of 0 means that the metadata hasn't been upgraded yet or + * the upgrade is currently in progress. If that is the case, disallow adding columns + * for tables with views. + */ + if (!childViewsResult.allViewsInSingleRegion() || table.getBaseColumnCount() == 0) { return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null); } else { http://git-wip-us.apache.org/repos/asf/phoenix/blob/39afa9f1/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java index a9f455a..9cd32e8 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java @@ -1826,7 +1826,10 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement return result; } - + + /** + * This closes the passed connection. + */ private PhoenixConnection addColumn(PhoenixConnection oldMetaConnection, String tableName, long timestamp, String columns, boolean addIfNotExists) throws SQLException { Properties props = new Properties(oldMetaConnection.getClientInfo()); props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(timestamp)); @@ -1956,7 +1959,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement columnsToAdd = PhoenixDatabaseMetaData.BASE_COLUMN_COUNT + " " + PInteger.INSTANCE.getSqlTypeName(); try { - addColumn(metaConnection, PhoenixDatabaseMetaData.SYSTEM_CATALOG, + metaConnection = addColumn(metaConnection, PhoenixDatabaseMetaData.SYSTEM_CATALOG, MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP, columnsToAdd, false); upgradeTo4_5_0(metaConnection); } catch (ColumnAlreadyExistsException ignored) { @@ -1965,6 +1968,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement * BASE_COLUMN_COUNT is already part of the meta-data schema as the signal that * the server side upgrade has finished or is in progress. */ + logger.debug("No need to run 4.5 upgrade"); } } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/39afa9f1/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java index 8d574ce..c829799 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java @@ -443,216 +443,238 @@ public class UpgradeUtil { buf, keyValue.getValueOffset(), keyValue.getValueLength()); } - public static void upgradeTo4_5_0(PhoenixConnection metaConnection) throws SQLException { - String getBaseTableAndViews = "SELECT " - + COLUMN_FAMILY + " AS BASE_PHYSICAL_TABLE, " - + TENANT_ID + ", " - + TABLE_SCHEM + " AS VIEW_SCHEMA, " - + TABLE_NAME + " AS VIEW_NAME " - + "FROM " + SYSTEM_CATALOG_NAME - + " WHERE " + COLUMN_FAMILY + " IS NOT NULL " // column_family column points to the physical table name. - + " AND " + COLUMN_NAME + " IS NULL " - + " AND " + LINK_TYPE + " = ? "; - // Build a map of base table name -> list of views on the table. - Map<String, List<ViewKey>> parentTableViewsMap = new HashMap<>(); - try (PreparedStatement stmt = metaConnection.prepareStatement(getBaseTableAndViews)) { - // Get back view rows that have links back to the base physical table. This takes care - // of cases when we have a hierarchy of views too. - stmt.setByte(1, LinkType.PHYSICAL_TABLE.getSerializedValue()); - try (ResultSet rs = stmt.executeQuery()) { - while (rs.next()) { - // this is actually SCHEMANAME.TABLENAME - String parentTable = rs.getString("BASE_PHYSICAL_TABLE"); - String tenantId = rs.getString(TENANT_ID); - String viewSchema = rs.getString("VIEW_SCHEMA"); - String viewName = rs.getString("VIEW_NAME"); - List<ViewKey> viewKeysList = parentTableViewsMap.get(parentTable); - if (viewKeysList == null) { - viewKeysList = new ArrayList<>(); - parentTableViewsMap.put(parentTable, viewKeysList); + /** + * Upgrade the metadata in the catalog table to enable adding columns to tables with views + * @param oldMetaConnection caller should take care of closing the passed connection appropriately + * @throws SQLException + */ + public static void upgradeTo4_5_0(PhoenixConnection oldMetaConnection) throws SQLException { + PhoenixConnection metaConnection = null; + try { + // Need to use own connection without any SCN to be able to read all data from SYSTEM.CATALOG + metaConnection = new PhoenixConnection(oldMetaConnection); + logger.info("Upgrading metadata to support adding columns to tables with views"); + String getBaseTableAndViews = "SELECT " + + COLUMN_FAMILY + " AS BASE_PHYSICAL_TABLE, " + + TENANT_ID + ", " + + TABLE_SCHEM + " AS VIEW_SCHEMA, " + + TABLE_NAME + " AS VIEW_NAME " + + "FROM " + SYSTEM_CATALOG_NAME + + " WHERE " + COLUMN_FAMILY + " IS NOT NULL " // column_family column points to the physical table name. + + " AND " + COLUMN_NAME + " IS NULL " + + " AND " + LINK_TYPE + " = ? "; + // Build a map of base table name -> list of views on the table. + Map<String, List<ViewKey>> parentTableViewsMap = new HashMap<>(); + try (PreparedStatement stmt = metaConnection.prepareStatement(getBaseTableAndViews)) { + // Get back view rows that have links back to the base physical table. This takes care + // of cases when we have a hierarchy of views too. + stmt.setByte(1, LinkType.PHYSICAL_TABLE.getSerializedValue()); + try (ResultSet rs = stmt.executeQuery()) { + while (rs.next()) { + // this is actually SCHEMANAME.TABLENAME + String parentTable = rs.getString("BASE_PHYSICAL_TABLE"); + String tenantId = rs.getString(TENANT_ID); + String viewSchema = rs.getString("VIEW_SCHEMA"); + String viewName = rs.getString("VIEW_NAME"); + List<ViewKey> viewKeysList = parentTableViewsMap.get(parentTable); + if (viewKeysList == null) { + viewKeysList = new ArrayList<>(); + parentTableViewsMap.put(parentTable, viewKeysList); + } + viewKeysList.add(new ViewKey(tenantId, viewSchema, viewName)); } - viewKeysList.add(new ViewKey(tenantId, viewSchema, viewName)); } } - } - - for (Entry<String, List<ViewKey>> entry : parentTableViewsMap.entrySet()) { - // Fetch column information for the base physical table - String physicalTable = entry.getKey(); - String baseTableSchemaName = SchemaUtil.getSchemaNameFromFullName(physicalTable).equals(StringUtil.EMPTY_STRING) ? null : SchemaUtil.getSchemaNameFromFullName(physicalTable); - String baseTableName = SchemaUtil.getTableNameFromFullName(physicalTable); - List<ColumnDetails> basePhysicalTableColumns = new ArrayList<>(); - - // Columns fetched in order of ordinal position - String fetchColumnInfoForBasePhysicalTable = "SELECT " + - COLUMN_NAME + "," + - COLUMN_FAMILY + "," + - DATA_TYPE + "," + - COLUMN_SIZE + "," + - DECIMAL_DIGITS + "," + - ORDINAL_POSITION + "," + - SORT_ORDER + "," + - ARRAY_SIZE + " " + - "FROM SYSTEM.CATALOG " + - "WHERE " + - "TABLE_SCHEM %s " + - "AND TABLE_NAME = ? " + - "AND COLUMN_NAME IS NOT NULL " + - "ORDER BY " + - ORDINAL_POSITION; - - PreparedStatement stmt = null; - if (baseTableSchemaName == null) { - fetchColumnInfoForBasePhysicalTable = - String.format(fetchColumnInfoForBasePhysicalTable, "IS NULL "); - stmt = metaConnection.prepareStatement(fetchColumnInfoForBasePhysicalTable); - stmt.setString(1, baseTableName); - } else { - fetchColumnInfoForBasePhysicalTable = - String.format(fetchColumnInfoForBasePhysicalTable, " = ? "); - stmt = metaConnection.prepareStatement(fetchColumnInfoForBasePhysicalTable); - stmt.setString(1, baseTableSchemaName); - stmt.setString(2, baseTableName); - } + boolean clearCache = false; + for (Entry<String, List<ViewKey>> entry : parentTableViewsMap.entrySet()) { + // Fetch column information for the base physical table + String physicalTable = entry.getKey(); + String baseTableSchemaName = SchemaUtil.getSchemaNameFromFullName(physicalTable).equals(StringUtil.EMPTY_STRING) ? null : SchemaUtil.getSchemaNameFromFullName(physicalTable); + String baseTableName = SchemaUtil.getTableNameFromFullName(physicalTable); + List<ColumnDetails> basePhysicalTableColumns = new ArrayList<>(); + + // Columns fetched in order of ordinal position + String fetchColumnInfoForBasePhysicalTable = "SELECT " + + COLUMN_NAME + "," + + COLUMN_FAMILY + "," + + DATA_TYPE + "," + + COLUMN_SIZE + "," + + DECIMAL_DIGITS + "," + + ORDINAL_POSITION + "," + + SORT_ORDER + "," + + ARRAY_SIZE + " " + + "FROM SYSTEM.CATALOG " + + "WHERE " + + "TABLE_SCHEM %s " + + "AND TABLE_NAME = ? " + + "AND COLUMN_NAME IS NOT NULL " + + "ORDER BY " + + ORDINAL_POSITION; + + PreparedStatement stmt = null; + if (baseTableSchemaName == null) { + fetchColumnInfoForBasePhysicalTable = + String.format(fetchColumnInfoForBasePhysicalTable, "IS NULL "); + stmt = metaConnection.prepareStatement(fetchColumnInfoForBasePhysicalTable); + stmt.setString(1, baseTableName); + } else { + fetchColumnInfoForBasePhysicalTable = + String.format(fetchColumnInfoForBasePhysicalTable, " = ? "); + stmt = metaConnection.prepareStatement(fetchColumnInfoForBasePhysicalTable); + stmt.setString(1, baseTableSchemaName); + stmt.setString(2, baseTableName); + } - try (ResultSet rs = stmt.executeQuery()) { - while (rs.next()) { - basePhysicalTableColumns.add(new ColumnDetails(rs.getString(COLUMN_FAMILY), rs - .getString(COLUMN_NAME), rs.getInt(ORDINAL_POSITION), rs - .getInt(DATA_TYPE), rs.getInt(COLUMN_SIZE), rs.getInt(DECIMAL_DIGITS), - rs.getInt(SORT_ORDER), rs.getInt(ARRAY_SIZE))); + try (ResultSet rs = stmt.executeQuery()) { + while (rs.next()) { + basePhysicalTableColumns.add(new ColumnDetails(rs.getString(COLUMN_FAMILY), rs + .getString(COLUMN_NAME), rs.getInt(ORDINAL_POSITION), rs + .getInt(DATA_TYPE), rs.getInt(COLUMN_SIZE), rs.getInt(DECIMAL_DIGITS), + rs.getInt(SORT_ORDER), rs.getInt(ARRAY_SIZE))); + } } - } - - // Fetch column information for all the views on the base physical table ordered by ordinal position. - List<ViewKey> viewKeys = entry.getValue(); - StringBuilder sb = new StringBuilder(); - sb.append("SELECT " + - TENANT_ID + "," + - TABLE_SCHEM + "," + - TABLE_NAME + "," + - COLUMN_NAME + "," + - COLUMN_FAMILY + "," + - DATA_TYPE + "," + - COLUMN_SIZE + "," + - DECIMAL_DIGITS + "," + - ORDINAL_POSITION + "," + - SORT_ORDER + "," + - ARRAY_SIZE + " " + - "FROM SYSTEM.CATALOG " + - "WHERE " + - COLUMN_NAME + " IS NOT NULL " + - "AND " + - ORDINAL_POSITION + " <= ? " + // fetch only those columns that would impact setting of base column count - "AND " + - "(" + TENANT_ID+ ", " + TABLE_SCHEM + ", " + TABLE_NAME + ") IN ("); - - int numViews = viewKeys.size(); - for (int i = 0; i < numViews; i++) { - sb.append(" (?, ?, ?) "); - if (i < numViews - 1) { - sb.append(", "); + + // Fetch column information for all the views on the base physical table ordered by ordinal position. + List<ViewKey> viewKeys = entry.getValue(); + StringBuilder sb = new StringBuilder(); + sb.append("SELECT " + + TENANT_ID + "," + + TABLE_SCHEM + "," + + TABLE_NAME + "," + + COLUMN_NAME + "," + + COLUMN_FAMILY + "," + + DATA_TYPE + "," + + COLUMN_SIZE + "," + + DECIMAL_DIGITS + "," + + ORDINAL_POSITION + "," + + SORT_ORDER + "," + + ARRAY_SIZE + " " + + "FROM SYSTEM.CATALOG " + + "WHERE " + + COLUMN_NAME + " IS NOT NULL " + + "AND " + + ORDINAL_POSITION + " <= ? " + // fetch only those columns that would impact setting of base column count + "AND " + + "(" + TENANT_ID+ ", " + TABLE_SCHEM + ", " + TABLE_NAME + ") IN ("); + + int numViews = viewKeys.size(); + for (int i = 0; i < numViews; i++) { + sb.append(" (?, ?, ?) "); + if (i < numViews - 1) { + sb.append(", "); + } } - } - sb.append(" ) "); - sb.append(" GROUP BY " + - TENANT_ID + "," + - TABLE_SCHEM + "," + - TABLE_NAME + "," + - COLUMN_NAME + "," + - COLUMN_FAMILY + "," + - DATA_TYPE + "," + - COLUMN_SIZE + "," + - DECIMAL_DIGITS + "," + - ORDINAL_POSITION + "," + - SORT_ORDER + "," + - ARRAY_SIZE + " " + - "ORDER BY " + - TENANT_ID + "," + TABLE_SCHEM + ", " + TABLE_NAME + ", " + ORDINAL_POSITION); - String fetchViewColumnsSql = sb.toString(); - stmt = metaConnection.prepareStatement(fetchViewColumnsSql); - int numColsInBaseTable = basePhysicalTableColumns.size(); - stmt.setInt(1, numColsInBaseTable); - int paramIndex = 1; - stmt.setInt(paramIndex++, numColsInBaseTable); - for (ViewKey view : viewKeys) { - stmt.setString(paramIndex++, view.tenantId); - stmt.setString(paramIndex++, view.schema); - stmt.setString(paramIndex++, view.name); - } - String currentTenantId = null; - String currentViewSchema = null; - String currentViewName = null; - try (ResultSet rs = stmt.executeQuery()) { - int numBaseTableColsMatched = 0; - boolean ignore = false; - boolean baseColumnCountUpserted = false; - while (rs.next()) { - String viewTenantId = rs.getString(TENANT_ID); - String viewSchema = rs.getString(TABLE_SCHEM); - String viewName = rs.getString(TABLE_NAME); - if (!(Objects.equal(viewTenantId, currentTenantId) && Objects.equal(viewSchema, currentViewSchema) && Objects.equal(viewName, currentViewName))) { - // We are about to iterate through columns of a different view. Check whether base column count was upserted. - // If it wasn't then it is likely the case that a column inherited from the base table was dropped from view. - if (currentViewName != null && !baseColumnCountUpserted && numBaseTableColsMatched < numColsInBaseTable) { - upsertBaseColumnCountInHeaderRow(metaConnection, currentTenantId, currentViewSchema, currentViewName, DIVERGED_VIEW_BASE_COLUMN_COUNT); + sb.append(" ) "); + sb.append(" GROUP BY " + + TENANT_ID + "," + + TABLE_SCHEM + "," + + TABLE_NAME + "," + + COLUMN_NAME + "," + + COLUMN_FAMILY + "," + + DATA_TYPE + "," + + COLUMN_SIZE + "," + + DECIMAL_DIGITS + "," + + ORDINAL_POSITION + "," + + SORT_ORDER + "," + + ARRAY_SIZE + " " + + "ORDER BY " + + TENANT_ID + "," + TABLE_SCHEM + ", " + TABLE_NAME + ", " + ORDINAL_POSITION); + String fetchViewColumnsSql = sb.toString(); + stmt = metaConnection.prepareStatement(fetchViewColumnsSql); + int numColsInBaseTable = basePhysicalTableColumns.size(); + stmt.setInt(1, numColsInBaseTable); + int paramIndex = 1; + stmt.setInt(paramIndex++, numColsInBaseTable); + for (ViewKey view : viewKeys) { + stmt.setString(paramIndex++, view.tenantId); + stmt.setString(paramIndex++, view.schema); + stmt.setString(paramIndex++, view.name); + } + String currentTenantId = null; + String currentViewSchema = null; + String currentViewName = null; + try (ResultSet rs = stmt.executeQuery()) { + int numBaseTableColsMatched = 0; + boolean ignore = false; + boolean baseColumnCountUpserted = false; + while (rs.next()) { + String viewTenantId = rs.getString(TENANT_ID); + String viewSchema = rs.getString(TABLE_SCHEM); + String viewName = rs.getString(TABLE_NAME); + if (!(Objects.equal(viewTenantId, currentTenantId) && Objects.equal(viewSchema, currentViewSchema) && Objects.equal(viewName, currentViewName))) { + // We are about to iterate through columns of a different view. Check whether base column count was upserted. + // If it wasn't then it is likely the case that a column inherited from the base table was dropped from view. + if (currentViewName != null && !baseColumnCountUpserted && numBaseTableColsMatched < numColsInBaseTable) { + upsertBaseColumnCountInHeaderRow(metaConnection, currentTenantId, currentViewSchema, currentViewName, DIVERGED_VIEW_BASE_COLUMN_COUNT); + clearCache = true; + } + // reset the values as we are now going to iterate over columns of a new view. + numBaseTableColsMatched = 0; + currentTenantId = viewTenantId; + currentViewSchema = viewSchema; + currentViewName = viewName; + ignore = false; + baseColumnCountUpserted = false; } - // reset the values as we are now going to iterate over columns of a new view. - numBaseTableColsMatched = 0; - currentTenantId = viewTenantId; - currentViewSchema = viewSchema; - currentViewName = viewName; - ignore = false; - baseColumnCountUpserted = false; - } - if (!ignore) { - /* - * Iterate over all the columns of the base physical table and the columns of the view. Compare the - * two till one of the following happens: - * - * 1) We run into a view column which is different from column in the base physical table. - * This means that the view has divorced itself from the base physical table. In such a case - * we will set a special value for the base column count. That special value will also be used - * on the server side to filter out the divorced view so that meta-data changes on the base - * physical table are not propagated to it. - * - * 2) Every physical table column is present in the view. In that case we set the base column count - * as the number of columns in the base physical table. At that point we ignore rest of the columns - * of the view. - * - */ - ColumnDetails baseTableColumn = basePhysicalTableColumns.get(numBaseTableColsMatched); - String columName = rs.getString(COLUMN_NAME); - String columnFamily = rs.getString(COLUMN_FAMILY); - int ordinalPos = rs.getInt(ORDINAL_POSITION); - int dataType = rs.getInt(DATA_TYPE); - int columnSize = rs.getInt(COLUMN_SIZE); - int decimalDigits = rs.getInt(DECIMAL_DIGITS); - int sortOrder = rs.getInt(SORT_ORDER); - int arraySize = rs.getInt(ARRAY_SIZE); - ColumnDetails viewColumn = new ColumnDetails(columnFamily, columName, ordinalPos, dataType, columnSize, decimalDigits, sortOrder, arraySize); - if (baseTableColumn.equals(viewColumn)) { - numBaseTableColsMatched++; - if (numBaseTableColsMatched == numColsInBaseTable) { - upsertBaseColumnCountInHeaderRow(metaConnection, viewTenantId, viewSchema, viewName, numColsInBaseTable); - // No need to ignore the rest of the columns of the view here since the - // query retrieved only those columns that had ordinal position <= numColsInBaseTable + if (!ignore) { + /* + * Iterate over all the columns of the base physical table and the columns of the view. Compare the + * two till one of the following happens: + * + * 1) We run into a view column which is different from column in the base physical table. + * This means that the view has divorced itself from the base physical table. In such a case + * we will set a special value for the base column count. That special value will also be used + * on the server side to filter out the divorced view so that meta-data changes on the base + * physical table are not propagated to it. + * + * 2) Every physical table column is present in the view. In that case we set the base column count + * as the number of columns in the base physical table. At that point we ignore rest of the columns + * of the view. + * + */ + ColumnDetails baseTableColumn = basePhysicalTableColumns.get(numBaseTableColsMatched); + String columName = rs.getString(COLUMN_NAME); + String columnFamily = rs.getString(COLUMN_FAMILY); + int ordinalPos = rs.getInt(ORDINAL_POSITION); + int dataType = rs.getInt(DATA_TYPE); + int columnSize = rs.getInt(COLUMN_SIZE); + int decimalDigits = rs.getInt(DECIMAL_DIGITS); + int sortOrder = rs.getInt(SORT_ORDER); + int arraySize = rs.getInt(ARRAY_SIZE); + ColumnDetails viewColumn = new ColumnDetails(columnFamily, columName, ordinalPos, dataType, columnSize, decimalDigits, sortOrder, arraySize); + if (baseTableColumn.equals(viewColumn)) { + numBaseTableColsMatched++; + if (numBaseTableColsMatched == numColsInBaseTable) { + upsertBaseColumnCountInHeaderRow(metaConnection, viewTenantId, viewSchema, viewName, numColsInBaseTable); + // No need to ignore the rest of the columns of the view here since the + // query retrieved only those columns that had ordinal position <= numColsInBaseTable + baseColumnCountUpserted = true; + clearCache = true; + } + } else { + // special value to denote that the view has divorced itself from the base physical table. + upsertBaseColumnCountInHeaderRow(metaConnection, viewTenantId, viewSchema, viewName, DIVERGED_VIEW_BASE_COLUMN_COUNT); baseColumnCountUpserted = true; + clearCache = true; + // ignore rest of the rows for the view. + ignore = true; } - } else { - // special value to denote that the view has divorced itself from the base physical table. - upsertBaseColumnCountInHeaderRow(metaConnection, viewTenantId, viewSchema, viewName, DIVERGED_VIEW_BASE_COLUMN_COUNT); - baseColumnCountUpserted = true; - // ignore rest of the rows for the view. - ignore = true; } } } + // set base column count for the header row of the base table too. We use this information + // to figure out whether the upgrade is in progress or hasn't started. + upsertBaseColumnCountInHeaderRow(metaConnection, null, baseTableSchemaName, baseTableName, BASE_TABLE_BASE_COLUMN_COUNT); + metaConnection.commit(); + } + // clear metadata cache on region servers to force loading of the latest metadata + if (clearCache) { + metaConnection.getQueryServices().clearCache(); + } + } finally { + if (metaConnection != null) { + metaConnection.close(); } - // set base column count for the header row of the base table too. We use this information - // to figure out whether the upgrade is in progress or hasn't started. - upsertBaseColumnCountInHeaderRow(metaConnection, null, baseTableSchemaName, baseTableName, BASE_TABLE_BASE_COLUMN_COUNT); - metaConnection.commit(); } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/39afa9f1/phoenix-protocol/src/main/PTable.proto ---------------------------------------------------------------------- diff --git a/phoenix-protocol/src/main/PTable.proto b/phoenix-protocol/src/main/PTable.proto index 348631f..cbbbdd6 100644 --- a/phoenix-protocol/src/main/PTable.proto +++ b/phoenix-protocol/src/main/PTable.proto @@ -83,4 +83,5 @@ message PTable { optional bytes indexType = 22; optional int64 statsTimeStamp = 23; optional bool storeNulls = 24; + optional int32 baseColumnCount = 25; }