[ https://issues.apache.org/jira/browse/PHOENIX-3534?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16533114#comment-16533114 ]
ASF GitHub Bot commented on PHOENIX-3534: ----------------------------------------- Github user JamesRTaylor commented on a diff in the pull request: https://github.com/apache/phoenix/pull/303#discussion_r200206862 --- Diff: phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java --- @@ -1809,180 +2256,97 @@ public void createTable(RpcController controller, CreateTableRequest request, } catch (Throwable t) { logger.error("createTable failed", t); ProtobufUtil.setControllerException(controller, - ServerUtil.createIOException(SchemaUtil.getTableName(schemaName, tableName), t)); + ServerUtil.createIOException(fullTableName, t)); } } + private void dropChildMetadata(byte[] schemaName, byte[] tableName, byte[] tenantIdBytes) + throws IOException, SQLException, ClassNotFoundException { + TableViewFinderResult childViewsResult = new TableViewFinderResult(); + findAllChildViews(tenantIdBytes, schemaName, tableName, childViewsResult); + if (childViewsResult.hasViews()) { + for (TableInfo viewInfo : childViewsResult.getResults()) { + byte[] viewTenantId = viewInfo.getTenantId(); + byte[] viewSchemaName = viewInfo.getSchemaName(); + byte[] viewName = viewInfo.getTableName(); + Properties props = new Properties(); + if (viewTenantId != null && viewTenantId.length != 0) + props.setProperty(PhoenixRuntime.TENANT_ID_ATTRIB, Bytes.toString(viewTenantId)); + try (PhoenixConnection connection = QueryUtil.getConnectionOnServer(env.getConfiguration()) + .unwrap(PhoenixConnection.class)) { + MetaDataClient client = new MetaDataClient(connection); + org.apache.phoenix.parse.TableName viewTableName = org.apache.phoenix.parse.TableName + .create(Bytes.toString(viewSchemaName), Bytes.toString(viewName)); + client.dropTable( + new DropTableStatement(viewTableName, PTableType.VIEW, false, true, true)); + } + } + } + } + private boolean execeededIndexQuota(PTableType tableType, PTable parentTable) { return PTableType.INDEX == tableType && parentTable.getIndexes().size() >= maxIndexesPerTable; } - - private void findAllChildViews(Region region, byte[] tenantId, PTable table, - TableViewFinder result, long clientTimeStamp, int clientVersion) throws IOException, SQLException { - TableViewFinder currResult = findChildViews(region, tenantId, table, clientVersion, false); - result.addResult(currResult); - for (ViewInfo viewInfo : currResult.getViewInfoList()) { - byte[] viewtenantId = viewInfo.getTenantId(); - byte[] viewSchema = viewInfo.getSchemaName(); - byte[] viewTable = viewInfo.getViewName(); - byte[] tableKey = SchemaUtil.getTableKey(viewtenantId, viewSchema, viewTable); - ImmutableBytesPtr cacheKey = new ImmutableBytesPtr(tableKey); - PTable view = loadTable(env, tableKey, cacheKey, clientTimeStamp, clientTimeStamp, clientVersion); - if (view == null) { - logger.warn("Found orphan tenant view row in SYSTEM.CATALOG with tenantId:" - + Bytes.toString(tenantId) + ", schema:" - + Bytes.toString(viewSchema) + ", table:" - + Bytes.toString(viewTable)); - continue; - } - findAllChildViews(region, viewtenantId, view, result, clientTimeStamp, clientVersion); - } - } - - // TODO use child link instead once splittable system catalog (PHOENIX-3534) is implemented - // and we have a separate table for links. - private TableViewFinder findChildViews_deprecated(Region region, byte[] tenantId, PTable table, byte[] linkTypeBytes, boolean stopAfterFirst) throws IOException { - byte[] schemaName = table.getSchemaName().getBytes(); - byte[] tableName = table.getTableName().getBytes(); - boolean isMultiTenant = table.isMultiTenant(); - Scan scan = new Scan(); - // If the table is multi-tenant, we need to check across all tenant_ids, - // so we can't constrain the row key. Otherwise, any views would have - // the same tenantId. - if (!isMultiTenant) { - byte[] startRow = ByteUtil.concat(tenantId, QueryConstants.SEPARATOR_BYTE_ARRAY); - byte[] stopRow = ByteUtil.nextKey(startRow); - scan.setStartRow(startRow); - scan.setStopRow(stopRow); - } - SingleColumnValueFilter linkFilter = new SingleColumnValueFilter(TABLE_FAMILY_BYTES, LINK_TYPE_BYTES, CompareOp.EQUAL, linkTypeBytes); - SingleColumnValueFilter tableTypeFilter = new SingleColumnValueFilter(TABLE_FAMILY_BYTES, TABLE_TYPE_BYTES, - CompareOp.EQUAL, PTableType.VIEW.getSerializedValue().getBytes()); - tableTypeFilter.setFilterIfMissing(false); - linkFilter.setFilterIfMissing(true); - byte[] suffix = ByteUtil.concat(QueryConstants.SEPARATOR_BYTE_ARRAY, SchemaUtil - .getPhysicalHBaseTableName(schemaName, tableName, table.isNamespaceMapped()) - .getBytes()); - SuffixFilter rowFilter = new SuffixFilter(suffix); - List<Filter> filters = Lists.<Filter>newArrayList(linkFilter,tableTypeFilter,rowFilter); - if (stopAfterFirst) { - filters.add(new PageFilter(1)); - } - FilterList filter = new FilterList(filters); - scan.setFilter(filter); - scan.addColumn(TABLE_FAMILY_BYTES, LINK_TYPE_BYTES); - scan.addColumn(TABLE_FAMILY_BYTES, TABLE_TYPE_BYTES); - scan.addColumn(TABLE_FAMILY_BYTES, TABLE_SEQ_NUM_BYTES); - - // Original region-only scanner modified due to PHOENIX-1208 - // RegionScanner scanner = region.getScanner(scan); - // The following *should* work, but doesn't due to HBASE-11837 - // TableName systemCatalogTableName = region.getTableDesc().getTableName(); - // HTableInterface hTable = env.getTable(systemCatalogTableName); - // These deprecated calls work around the issue - try (HTableInterface hTable = ServerUtil.getHTableForCoprocessorScan(env, - region.getTableDesc().getTableName().getName())) { - boolean allViewsInCurrentRegion = true; - int numOfChildViews = 0; - List<ViewInfo> viewInfoList = Lists.newArrayList(); - try (ResultScanner scanner = hTable.getScanner(scan)) { - for (Result result = scanner.next(); (result != null); result = scanner.next()) { - numOfChildViews++; - ImmutableBytesWritable ptr = new ImmutableBytesWritable(); - ResultTuple resultTuple = new ResultTuple(result); - resultTuple.getKey(ptr); - byte[] key = ptr.copyBytes(); - if (checkTableKeyInRegion(key, region) != null) { - allViewsInCurrentRegion = false; - } - 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)); - } - TableViewFinder tableViewFinderResult = new TableViewFinder(viewInfoList); - if (numOfChildViews > 0 && !allViewsInCurrentRegion) { - tableViewFinderResult.setAllViewsNotInSingleRegion(); - } - return tableViewFinderResult; + + private void findAncestorViewsOfIndex(byte[] tenantId, byte[] schemaName, byte[] indexName, + TableViewFinderResult result, boolean isNamespaceMapped) throws IOException { + try (Table hTable = + env.getTable(SchemaUtil.getPhysicalTableName( + PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME_BYTES, env.getConfiguration()))) { + TableViewFinderResult currentResult = + ViewFinder.findParentViewofIndex(hTable, tenantId, schemaName, indexName); + if (currentResult.getResults().size() == 1) { + result.addResult(currentResult); + TableInfo tableInfo = currentResult.getResults().get(0); + findAncestorViews(tableInfo.getTenantId(), tableInfo.getSchemaName(), + tableInfo.getTableName(), result, isNamespaceMapped); } + // else this is an index on a regular table and so we don't need to combine columns } } - private TableViewFinder findChildViews_4_11(Region region, byte[] tenantId, byte[] schemaName, byte[] tableName, boolean stopAfterFirst) throws IOException { - Scan scan = new Scan(); - byte[] startRow = SchemaUtil.getTableKey(tenantId, schemaName, tableName); - byte[] stopRow = ByteUtil.nextKey(startRow); - scan.setStartRow(startRow); - scan.setStopRow(stopRow); - SingleColumnValueFilter linkFilter = new SingleColumnValueFilter(TABLE_FAMILY_BYTES, LINK_TYPE_BYTES, CompareOp.EQUAL, CHILD_TABLE_BYTES); - Filter filter = linkFilter; - linkFilter.setFilterIfMissing(true); - if (stopAfterFirst) { - filter = new FilterList(linkFilter, new PageFilter(1)); - } - scan.setFilter(filter); - scan.addColumn(TABLE_FAMILY_BYTES, LINK_TYPE_BYTES); - scan.addColumn(TABLE_FAMILY_BYTES, PARENT_TENANT_ID_BYTES); - - // Original region-only scanner modified due to PHOENIX-1208 - // RegionScanner scanner = region.getScanner(scan); - // The following *should* work, but doesn't due to HBASE-11837 - // TableName systemCatalogTableName = region.getTableDesc().getTableName(); - // HTableInterface hTable = env.getTable(systemCatalogTableName); - // These deprecated calls work around the issue - try (HTableInterface hTable = ServerUtil.getHTableForCoprocessorScan(env, - region.getTableDesc().getTableName().getName())) { - boolean allViewsInCurrentRegion = true; - int numOfChildViews = 0; - List<ViewInfo> viewInfoList = Lists.newArrayList(); - try (ResultScanner scanner = hTable.getScanner(scan)) { - for (Result result = scanner.next(); (result != null); result = scanner.next()) { - numOfChildViews++; - ImmutableBytesWritable ptr = new ImmutableBytesWritable(); - ResultTuple resultTuple = new ResultTuple(result); - resultTuple.getKey(ptr); - byte[] key = ptr.copyBytes(); - if (checkTableKeyInRegion(key, region) != null) { - allViewsInCurrentRegion = false; - } - 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)); - } - TableViewFinder tableViewFinderResult = new TableViewFinder(viewInfoList); - if (numOfChildViews > 0 && !allViewsInCurrentRegion) { - tableViewFinderResult.setAllViewsNotInSingleRegion(); - } - return tableViewFinderResult; + private void findAncestorViews(byte[] tenantId, byte[] schemaName, byte[] tableName, + TableViewFinderResult result, boolean isNamespaceMapped) throws IOException { + try (Table hTable = + env.getTable(SchemaUtil.getPhysicalTableName( + PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME_BYTES, env.getConfiguration()))) { + ViewFinder.findAllRelatives(hTable, tenantId, schemaName, tableName, + LinkType.PARENT_TABLE, result); + if (!isNamespaceMapped || schemaName.length==0) { + // the child->parent link is overwritten by the child->physical table link for first + // level children of base table when namespace mapping is disabled or if the parent + // table doesn't have a schema as both the parent table name and physical table name + // are the same. + // When namespace mapping is enabled the physical table name is of the form S:T + // while the table name is of the form S.T so we need to query for the + // PHYSICAL_TABLE link --- End diff -- Since the linking rows are being re-written I believe in 4.15, should we change this behavior? > Support multi region SYSTEM.CATALOG table > ----------------------------------------- > > Key: PHOENIX-3534 > URL: https://issues.apache.org/jira/browse/PHOENIX-3534 > Project: Phoenix > Issue Type: Bug > Reporter: James Taylor > Assignee: Thomas D'Silva > Priority: Major > Fix For: 5.0.0, 4.15.0 > > Attachments: PHOENIX-3534.patch > > > Currently Phoenix requires that the SYSTEM.CATALOG table is single region > based on the server-side row locks being held for operations that impact a > table and all of it's views. For example, adding/removing a column from a > base table pushes this change to all views. > As an alternative to making the SYSTEM.CATALOG transactional (PHOENIX-2431), > when a new table is created we can do a lazy cleanup of any rows that may be > left over from a failed DDL call (kudos to [~lhofhansl] for coming up with > this idea). To implement this efficiently, we'd need to also do PHOENIX-2051 > so that we can efficiently find derived views. > The implementation would rely on an optimistic concurrency model based on > checking our sequence numbers for each table/view before/after updating. Each > table/view row would be individually locked for their change (metadata for a > view or table cannot span regions due to our split policy), with the sequence > number being incremented under lock and then returned to the client. -- This message was sent by Atlassian JIRA (v7.6.3#76005)