Skip to content

Commit

Permalink
PHOENIX-3900 Backward compatibility fails with TNF exception when del…
Browse files Browse the repository at this point in the history
…eting table with a view
  • Loading branch information
Thomas committed Jun 1, 2017
1 parent 9379344 commit 5fe6605
Showing 1 changed file with 84 additions and 60 deletions.
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -1653,30 +1653,25 @@ private static RowLock acquireLock(Region region, byte[] key, List<RowLock> lock


private static final byte[] CHILD_TABLE_BYTES = new byte[] {PTable.LinkType.CHILD_TABLE.getSerializedValue()}; private static final byte[] CHILD_TABLE_BYTES = new byte[] {PTable.LinkType.CHILD_TABLE.getSerializedValue()};


private void findAllChildViews(Region region, byte[] tenantId, PTable table, TableViewFinderResult result, long clientTimeStamp) throws IOException, SQLException {
TableViewFinderResult currResult = findChildViews(region, tenantId, table); private void findAllChildViews(Region region, byte[] tenantId, PTable table,
TableViewFinder result, long clientTimeStamp) throws IOException, SQLException {
TableViewFinder currResult = findChildViews(region, tenantId, table);
result.addResult(currResult); result.addResult(currResult);
for (Result viewResult : currResult.getResults()) { for (ViewInfo viewInfo : currResult.getViewInfoList()) {
byte[][] rowViewKeyMetaData = new byte[5][]; byte[] viewtenantId = viewInfo.getTenantId();
getVarChars(viewResult.getRow(), 5, rowViewKeyMetaData); byte[] viewSchema = viewInfo.getSchemaName();
byte[] viewtenantId = rowViewKeyMetaData[PhoenixDatabaseMetaData.COLUMN_NAME_INDEX]; byte[] viewTable = viewInfo.getViewName();
byte[] viewSchema = SchemaUtil.getSchemaNameFromFullName(rowViewKeyMetaData[PhoenixDatabaseMetaData.FAMILY_NAME_INDEX]).getBytes(); byte[] tableKey = SchemaUtil.getTableKey(viewtenantId, viewSchema, viewTable);
byte[] viewTable = SchemaUtil.getTableNameFromFullName(rowViewKeyMetaData[PhoenixDatabaseMetaData.FAMILY_NAME_INDEX]).getBytes();
byte[] tableKey =
SchemaUtil.getTableKey(viewtenantId,
viewSchema,
viewTable);
ImmutableBytesPtr cacheKey = new ImmutableBytesPtr(tableKey); ImmutableBytesPtr cacheKey = new ImmutableBytesPtr(tableKey);
PTable view = PTable view = loadTable(env, tableKey, cacheKey, clientTimeStamp, clientTimeStamp);
loadTable(env, tableKey, cacheKey, clientTimeStamp,
clientTimeStamp);
findAllChildViews(region, viewtenantId, view, result, clientTimeStamp); findAllChildViews(region, viewtenantId, view, result, clientTimeStamp);
} }
} }


// TODO remove this in 4.13 release // TODO remove this in 4.13 release
@Deprecated @Deprecated
private TableViewFinderResult findChildViews_deprecated(Region region, byte[] tenantId, PTable table, byte[] linkTypeBytes) throws IOException { private TableViewFinder findChildViews_deprecated(Region region, byte[] tenantId, PTable table, byte[] linkTypeBytes) throws IOException {
byte[] schemaName = table.getSchemaName().getBytes(); byte[] schemaName = table.getSchemaName().getBytes();
byte[] tableName = table.getTableName().getBytes(); byte[] tableName = table.getTableName().getBytes();
boolean isMultiTenant = table.isMultiTenant(); boolean isMultiTenant = table.isMultiTenant();
Expand Down Expand Up @@ -1716,7 +1711,7 @@ private TableViewFinderResult findChildViews_deprecated(Region region, byte[] te
try { try {
boolean allViewsInCurrentRegion = true; boolean allViewsInCurrentRegion = true;
int numOfChildViews = 0; int numOfChildViews = 0;
List<Result> results = Lists.newArrayList(); List<ViewInfo> viewInfoList = Lists.newArrayList();
ResultScanner scanner = hTable.getScanner(scan); ResultScanner scanner = hTable.getScanner(scan);
try { try {
for (Result result = scanner.next(); (result != null); result = scanner.next()) { for (Result result = scanner.next(); (result != null); result = scanner.next()) {
Expand All @@ -1728,9 +1723,14 @@ private TableViewFinderResult findChildViews_deprecated(Region region, byte[] te
if (checkTableKeyInRegion(key, region) != null) { if (checkTableKeyInRegion(key, region) != null) {
allViewsInCurrentRegion = false; allViewsInCurrentRegion = false;
} }
results.add(result); byte[][] rowKeyMetaData = new byte[3][];
getVarChars(result.getRow(), 3, rowKeyMetaData);
byte[] viewTenantId = rowKeyMetaData[PhoenixDatabaseMetaData.TENANT_ID_INDEX];
byte[] viewSchemaName = rowKeyMetaData[PhoenixDatabaseMetaData.SCHEMA_NAME_INDEX];
byte[] viewName = rowKeyMetaData[PhoenixDatabaseMetaData.TABLE_NAME_INDEX];
viewInfoList.add(new ViewInfo(viewTenantId, viewSchemaName, viewName));
} }
TableViewFinderResult tableViewFinderResult = new TableViewFinderResult(results); TableViewFinder tableViewFinderResult = new TableViewFinder(viewInfoList);
if (numOfChildViews > 0 && !allViewsInCurrentRegion) { if (numOfChildViews > 0 && !allViewsInCurrentRegion) {
tableViewFinderResult.setAllViewsNotInSingleRegion(); tableViewFinderResult.setAllViewsNotInSingleRegion();
} }
Expand All @@ -1743,7 +1743,7 @@ private TableViewFinderResult findChildViews_deprecated(Region region, byte[] te
} }
} }


private TableViewFinderResult findChildViews_4_11(Region region, byte[] tenantId, byte[] schemaName, byte[] tableName) throws IOException { private TableViewFinder findChildViews_4_11(Region region, byte[] tenantId, byte[] schemaName, byte[] tableName) throws IOException {
Scan scan = new Scan(); Scan scan = new Scan();
byte[] startRow = SchemaUtil.getTableKey(tenantId, schemaName, tableName); byte[] startRow = SchemaUtil.getTableKey(tenantId, schemaName, tableName);
byte[] stopRow = ByteUtil.nextKey(startRow); byte[] stopRow = ByteUtil.nextKey(startRow);
Expand All @@ -1766,7 +1766,7 @@ private TableViewFinderResult findChildViews_4_11(Region region, byte[] tenantId
try { try {
boolean allViewsInCurrentRegion = true; boolean allViewsInCurrentRegion = true;
int numOfChildViews = 0; int numOfChildViews = 0;
List<Result> results = Lists.newArrayList(); List<ViewInfo> viewInfoList = Lists.newArrayList();
ResultScanner scanner = hTable.getScanner(scan); ResultScanner scanner = hTable.getScanner(scan);
try { try {
for (Result result = scanner.next(); (result != null); result = scanner.next()) { for (Result result = scanner.next(); (result != null); result = scanner.next()) {
Expand All @@ -1778,9 +1778,14 @@ private TableViewFinderResult findChildViews_4_11(Region region, byte[] tenantId
if (checkTableKeyInRegion(key, region) != null) { if (checkTableKeyInRegion(key, region) != null) {
allViewsInCurrentRegion = false; allViewsInCurrentRegion = false;
} }
results.add(result); byte[][] rowViewKeyMetaData = new byte[5][];
getVarChars(result.getRow(), 5, rowViewKeyMetaData);
byte[] viewTenantId = rowViewKeyMetaData[PhoenixDatabaseMetaData.COLUMN_NAME_INDEX];
byte[] viewSchemaName = SchemaUtil.getSchemaNameFromFullName(rowViewKeyMetaData[PhoenixDatabaseMetaData.FAMILY_NAME_INDEX]).getBytes();
byte[] viewName = SchemaUtil.getTableNameFromFullName(rowViewKeyMetaData[PhoenixDatabaseMetaData.FAMILY_NAME_INDEX]).getBytes();
viewInfoList.add(new ViewInfo(viewTenantId, viewSchemaName, viewName));
} }
TableViewFinderResult tableViewFinderResult = new TableViewFinderResult(results); TableViewFinder tableViewFinderResult = new TableViewFinder(viewInfoList);
if (numOfChildViews > 0 && !allViewsInCurrentRegion) { if (numOfChildViews > 0 && !allViewsInCurrentRegion) {
tableViewFinderResult.setAllViewsNotInSingleRegion(); tableViewFinderResult.setAllViewsNotInSingleRegion();
} }
Expand All @@ -1796,7 +1801,7 @@ private TableViewFinderResult findChildViews_4_11(Region region, byte[] tenantId
private static final byte[] PHYSICAL_TABLE_BYTES = private static final byte[] PHYSICAL_TABLE_BYTES =
new byte[] { PTable.LinkType.PHYSICAL_TABLE.getSerializedValue() }; new byte[] { PTable.LinkType.PHYSICAL_TABLE.getSerializedValue() };


private TableViewFinderResult findChildViews(Region region, byte[] tenantId, PTable table) private TableViewFinder findChildViews(Region region, byte[] tenantId, PTable table)
throws IOException, SQLException { throws IOException, SQLException {
byte[] tableKey = byte[] tableKey =
SchemaUtil.getTableKey(ByteUtil.EMPTY_BYTE_ARRAY, SchemaUtil.getTableKey(ByteUtil.EMPTY_BYTE_ARRAY,
Expand Down Expand Up @@ -1945,7 +1950,7 @@ private MetaDataMutationResult doDropTable(byte[] key, byte[] tenantId, byte[] s


if (tableType == PTableType.TABLE || tableType == PTableType.SYSTEM) { if (tableType == PTableType.TABLE || tableType == PTableType.SYSTEM) {
// Handle any child views that exist // Handle any child views that exist
TableViewFinderResult tableViewFinderResult = findChildViews(region, tenantId, table); TableViewFinder tableViewFinderResult = findChildViews(region, tenantId, table);
if (tableViewFinderResult.hasViews()) { if (tableViewFinderResult.hasViews()) {
if (isCascade) { if (isCascade) {
if (tableViewFinderResult.allViewsInMultipleRegions()) { if (tableViewFinderResult.allViewsInMultipleRegions()) {
Expand All @@ -1955,12 +1960,10 @@ private MetaDataMutationResult doDropTable(byte[] key, byte[] tenantId, byte[] s
EnvironmentEdgeManager.currentTimeMillis(), null); EnvironmentEdgeManager.currentTimeMillis(), null);
} else if (tableViewFinderResult.allViewsInSingleRegion()) { } else if (tableViewFinderResult.allViewsInSingleRegion()) {
// Recursively delete views - safe as all the views as all in the same region // Recursively delete views - safe as all the views as all in the same region
for (Result viewResult : tableViewFinderResult.getResults()) { for (ViewInfo viewInfo : tableViewFinderResult.getViewInfoList()) {
byte[][] rowViewKeyMetaData = new byte[5][]; byte[] viewTenantId = viewInfo.getTenantId();
getVarChars(viewResult.getRow(), 5, rowViewKeyMetaData); byte[] viewSchemaName = viewInfo.getSchemaName();
byte[] viewTenantId = rowViewKeyMetaData[PhoenixDatabaseMetaData.COLUMN_NAME_INDEX]; byte[] viewName = viewInfo.getViewName();
byte[] viewSchemaName = SchemaUtil.getSchemaNameFromFullName(rowViewKeyMetaData[PhoenixDatabaseMetaData.FAMILY_NAME_INDEX]).getBytes();
byte[] viewName = SchemaUtil.getTableNameFromFullName(rowViewKeyMetaData[PhoenixDatabaseMetaData.FAMILY_NAME_INDEX]).getBytes();
byte[] viewKey = SchemaUtil.getTableKey(viewTenantId, viewSchemaName, viewName); byte[] viewKey = SchemaUtil.getTableKey(viewTenantId, viewSchemaName, viewName);
Delete delete = new Delete(viewKey, clientTimeStamp); Delete delete = new Delete(viewKey, clientTimeStamp);
rowsToDelete.add(delete); rowsToDelete.add(delete);
Expand Down Expand Up @@ -2311,7 +2314,7 @@ private boolean switchAttribute(PTable table, boolean currAttribute, List<Mutati
} }


private MetaDataMutationResult addColumnsAndTablePropertiesToChildViews(PTable basePhysicalTable, List<Mutation> tableMetadata, List<Mutation> mutationsForAddingColumnsToViews, byte[] schemaName, byte[] tableName, private MetaDataMutationResult addColumnsAndTablePropertiesToChildViews(PTable basePhysicalTable, List<Mutation> tableMetadata, List<Mutation> mutationsForAddingColumnsToViews, byte[] schemaName, byte[] tableName,
List<ImmutableBytesPtr> invalidateList, long clientTimeStamp, TableViewFinderResult childViewsResult, List<ImmutableBytesPtr> invalidateList, long clientTimeStamp, TableViewFinder childViewsResult,
Region region, List<RowLock> locks) throws IOException, SQLException { Region region, List<RowLock> locks) throws IOException, SQLException {
List<PutWithOrdinalPosition> columnPutsForBaseTable = Lists.newArrayListWithExpectedSize(tableMetadata.size()); List<PutWithOrdinalPosition> columnPutsForBaseTable = Lists.newArrayListWithExpectedSize(tableMetadata.size());
Map<TableProperty, Cell> tablePropertyCellMap = Maps.newHashMapWithExpectedSize(tableMetadata.size()); Map<TableProperty, Cell> tablePropertyCellMap = Maps.newHashMapWithExpectedSize(tableMetadata.size());
Expand Down Expand Up @@ -2348,15 +2351,13 @@ else if (pkCount <= COLUMN_NAME_INDEX
} }
// Sort the puts by ordinal position // Sort the puts by ordinal position
Collections.sort(columnPutsForBaseTable); Collections.sort(columnPutsForBaseTable);
for (Result viewResult : childViewsResult.getResults()) { for (ViewInfo viewInfo : childViewsResult.getViewInfoList()) {
short deltaNumPkColsSoFar = 0; short deltaNumPkColsSoFar = 0;
short columnsAddedToView = 0; short columnsAddedToView = 0;
short columnsAddedToBaseTable = 0; short columnsAddedToBaseTable = 0;
byte[][] rowViewKeyMetaData = new byte[5][]; byte[] tenantId = viewInfo.getTenantId();
getVarChars(viewResult.getRow(), 5, rowViewKeyMetaData); byte[] schema = viewInfo.getSchemaName();
byte[] tenantId = rowViewKeyMetaData[PhoenixDatabaseMetaData.COLUMN_NAME_INDEX]; byte[] table = viewInfo.getViewName();
byte[] schema = SchemaUtil.getSchemaNameFromFullName(rowViewKeyMetaData[PhoenixDatabaseMetaData.FAMILY_NAME_INDEX]).getBytes();
byte[] table = SchemaUtil.getTableNameFromFullName(rowViewKeyMetaData[PhoenixDatabaseMetaData.FAMILY_NAME_INDEX]).getBytes();
byte[] viewKey = SchemaUtil.getTableKey(tenantId, schema, table); byte[] viewKey = SchemaUtil.getTableKey(tenantId, schema, table);


// lock the rows corresponding to views so that no other thread can modify the view meta-data // lock the rows corresponding to views so that no other thread can modify the view meta-data
Expand Down Expand Up @@ -2660,7 +2661,7 @@ private MetaDataMutationResult dropColumnsFromChildViews(Region region,
PTable basePhysicalTable, List<RowLock> locks, List<Mutation> tableMetadata, PTable basePhysicalTable, List<RowLock> locks, List<Mutation> tableMetadata,
List<Mutation> mutationsForAddingColumnsToViews, byte[] schemaName, byte[] tableName, List<Mutation> mutationsForAddingColumnsToViews, byte[] schemaName, byte[] tableName,
List<ImmutableBytesPtr> invalidateList, long clientTimeStamp, List<ImmutableBytesPtr> invalidateList, long clientTimeStamp,
TableViewFinderResult childViewsResult, List<byte[]> tableNamesToDelete, List<SharedTableState> sharedTablesToDelete) TableViewFinder childViewsResult, List<byte[]> tableNamesToDelete, List<SharedTableState> sharedTablesToDelete)
throws IOException, SQLException { throws IOException, SQLException {
List<Delete> columnDeletesForBaseTable = new ArrayList<>(tableMetadata.size()); List<Delete> columnDeletesForBaseTable = new ArrayList<>(tableMetadata.size());
// Isolate the deletes relevant to dropping columns. Also figure out what kind of columns // Isolate the deletes relevant to dropping columns. Also figure out what kind of columns
Expand All @@ -2676,13 +2677,11 @@ private MetaDataMutationResult dropColumnsFromChildViews(Region region,
} }
} }
} }
for (Result viewResult : childViewsResult.getResults()) { for (ViewInfo viewInfo : childViewsResult.getViewInfoList()) {
short numColsDeleted = 0; short numColsDeleted = 0;
byte[][] rowViewKeyMetaData = new byte[5][]; byte[] viewTenantId = viewInfo.getTenantId();
getVarChars(viewResult.getRow(), 5, rowViewKeyMetaData); byte[] viewSchemaName = viewInfo.getSchemaName();
byte[] viewTenantId = rowViewKeyMetaData[PhoenixDatabaseMetaData.COLUMN_NAME_INDEX]; byte[] viewName = viewInfo.getViewName();
byte[] viewSchemaName = SchemaUtil.getSchemaNameFromFullName(rowViewKeyMetaData[PhoenixDatabaseMetaData.FAMILY_NAME_INDEX]).getBytes();
byte[] viewName = SchemaUtil.getTableNameFromFullName(rowViewKeyMetaData[PhoenixDatabaseMetaData.FAMILY_NAME_INDEX]).getBytes();
byte[] viewKey = SchemaUtil.getTableKey(viewTenantId, viewSchemaName, viewName); byte[] viewKey = SchemaUtil.getTableKey(viewTenantId, viewSchemaName, viewName);


// lock the rows corresponding to views so that no other thread can modify the view // lock the rows corresponding to views so that no other thread can modify the view
Expand Down Expand Up @@ -2980,7 +2979,7 @@ public MetaDataMutationResult updateMutation(PTable table, byte[][] rowKeyMetaDa
// Size for worst case - all new columns are PK column // Size for worst case - all new columns are PK column
List<Mutation> mutationsForAddingColumnsToViews = Lists.newArrayListWithExpectedSize(tableMetaData.size() * ( 1 + table.getIndexes().size())); List<Mutation> mutationsForAddingColumnsToViews = Lists.newArrayListWithExpectedSize(tableMetaData.size() * ( 1 + table.getIndexes().size()));
if (type == PTableType.TABLE || type == PTableType.SYSTEM) { if (type == PTableType.TABLE || type == PTableType.SYSTEM) {
TableViewFinderResult childViewsResult = new TableViewFinderResult(); TableViewFinder childViewsResult = new TableViewFinder();
findAllChildViews(region, tenantId, table, childViewsResult, clientTimeStamp); findAllChildViews(region, tenantId, table, childViewsResult, clientTimeStamp);
if (childViewsResult.hasViews()) { if (childViewsResult.hasViews()) {
/* /*
Expand All @@ -3004,7 +3003,7 @@ public MetaDataMutationResult updateMutation(PTable table, byte[][] rowKeyMetaDa
return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION,
EnvironmentEdgeManager.currentTimeMillis(), null); EnvironmentEdgeManager.currentTimeMillis(), null);
} else { } else {
mutationsForAddingColumnsToViews = new ArrayList<>(childViewsResult.getResults().size() * tableMetaData.size()); mutationsForAddingColumnsToViews = new ArrayList<>(childViewsResult.getViewInfoList().size() * tableMetaData.size());
MetaDataMutationResult mutationResult = addColumnsAndTablePropertiesToChildViews(table, tableMetaData, mutationsForAddingColumnsToViews, schemaName, tableName, invalidateList, clientTimeStamp, MetaDataMutationResult mutationResult = addColumnsAndTablePropertiesToChildViews(table, tableMetaData, mutationsForAddingColumnsToViews, schemaName, tableName, invalidateList, clientTimeStamp,
childViewsResult, region, locks); childViewsResult, region, locks);
// return if we were not able to add the column successfully // return if we were not able to add the column successfully
Expand Down Expand Up @@ -3256,7 +3255,7 @@ public MetaDataMutationResult updateMutation(PTable table, byte[][] rowKeyMetaDa


PTableType type = table.getType(); PTableType type = table.getType();
if (type == PTableType.TABLE || type == PTableType.SYSTEM) { if (type == PTableType.TABLE || type == PTableType.SYSTEM) {
TableViewFinderResult childViewsResult = new TableViewFinderResult(); TableViewFinder childViewsResult = new TableViewFinder();
findAllChildViews(region, tenantId, table, childViewsResult, clientTimeStamp); findAllChildViews(region, tenantId, table, childViewsResult, clientTimeStamp);
if (childViewsResult.hasViews()) { if (childViewsResult.hasViews()) {
MetaDataMutationResult mutationResult = MetaDataMutationResult mutationResult =
Expand Down Expand Up @@ -3639,52 +3638,77 @@ private static MetaDataMutationResult checkSchemaKeyInRegion(byte[] key, Region
return checkKeyInRegion(key, region, MutationCode.SCHEMA_NOT_IN_REGION); return checkKeyInRegion(key, region, MutationCode.SCHEMA_NOT_IN_REGION);


} }

private static class ViewInfo {
private byte[] tenantId;
private byte[] schemaName;
private byte[] viewName;

public ViewInfo(byte[] tenantId, byte[] schemaName, byte[] viewName) {
super();
this.tenantId = tenantId;
this.schemaName = schemaName;
this.viewName = viewName;
}

public byte[] getTenantId() {
return tenantId;
}

public byte[] getSchemaName() {
return schemaName;
}

public byte[] getViewName() {
return viewName;
}
}


/** /**
* Certain operations, such as DROP TABLE are not allowed if there a table has child views. This class wraps the * Certain operations, such as DROP TABLE are not allowed if there a table has child views. This class wraps the
* Results of a scanning the Phoenix Metadata for child views for a specific table and stores an additional flag for * Results of a scanning the Phoenix Metadata for child views for a specific table and stores an additional flag for
* whether whether SYSTEM.CATALOG has split across multiple regions. * whether whether SYSTEM.CATALOG has split across multiple regions.
*/ */
private static class TableViewFinderResult { private static class TableViewFinder {


private List<Result> results = Lists.newArrayList(); private List<ViewInfo> viewInfoList = Lists.newArrayList();
private boolean allViewsNotInSingleRegion = false; private boolean allViewsNotInSingleRegion = false;


private TableViewFinderResult() { private TableViewFinder() {
} }


private TableViewFinderResult(List<Result> results) { private TableViewFinder(List<ViewInfo> viewInfoList) {
this.results = results; this.viewInfoList = viewInfoList;
} }


public boolean hasViews() { public boolean hasViews() {
return !results.isEmpty(); return !viewInfoList.isEmpty();
} }


private void setAllViewsNotInSingleRegion() { private void setAllViewsNotInSingleRegion() {
allViewsNotInSingleRegion = true; allViewsNotInSingleRegion = true;
} }


private List<Result> getResults() { private List<ViewInfo> getViewInfoList() {
return results; return viewInfoList;
} }


/** /**
* Returns true is the table has views and they are all in the same HBase region. * Returns true is the table has views and they are all in the same HBase region.
*/ */
private boolean allViewsInSingleRegion() { private boolean allViewsInSingleRegion() {
return results.size() > 0 && !allViewsNotInSingleRegion; return viewInfoList.size() > 0 && !allViewsNotInSingleRegion;
} }


/** /**
* Returns true is the table has views and they are all NOT in the same HBase region. * Returns true is the table has views and they are all NOT in the same HBase region.
*/ */
private boolean allViewsInMultipleRegions() { private boolean allViewsInMultipleRegions() {
return results.size() > 0 && allViewsNotInSingleRegion; return viewInfoList.size() > 0 && allViewsNotInSingleRegion;
} }


private void addResult(TableViewFinderResult result) { private void addResult(TableViewFinder result) {
this.results.addAll(result.getResults()); this.viewInfoList.addAll(result.getViewInfoList());
if (result.allViewsInMultipleRegions()) { if (result.allViewsInMultipleRegions()) {
this.setAllViewsNotInSingleRegion(); this.setAllViewsNotInSingleRegion();
} }
Expand Down

0 comments on commit 5fe6605

Please sign in to comment.