Repository: phoenix Updated Branches: refs/heads/4.x-HBase-0.98 366e7a779 -> 7e432be79
http://git-wip-us.apache.org/repos/asf/phoenix/blob/7e432be7/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java index 523f684..dbc65d4 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java @@ -41,7 +41,9 @@ import java.util.TreeSet; import javax.annotation.Nullable; +import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.KeyValue; +import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding; import org.apache.hadoop.hbase.util.Bytes; import org.apache.phoenix.exception.SQLExceptionCode; @@ -52,14 +54,19 @@ import org.apache.phoenix.jdbc.PhoenixConnection; import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData; import org.apache.phoenix.query.KeyRange; import org.apache.phoenix.query.QueryConstants; +import org.apache.phoenix.query.QueryServices; +import org.apache.phoenix.query.QueryServicesOptions; import org.apache.phoenix.schema.AmbiguousColumnException; import org.apache.phoenix.schema.ColumnFamilyNotFoundException; import org.apache.phoenix.schema.ColumnNotFoundException; +import org.apache.phoenix.schema.MetaDataClient; import org.apache.phoenix.schema.PColumn; import org.apache.phoenix.schema.PColumnFamily; import org.apache.phoenix.schema.PDatum; import org.apache.phoenix.schema.PName; +import org.apache.phoenix.schema.PNameFactory; import org.apache.phoenix.schema.PTable; +import org.apache.phoenix.schema.PTableType; import org.apache.phoenix.schema.RowKeySchema; import org.apache.phoenix.schema.RowKeySchema.RowKeySchemaBuilder; import org.apache.phoenix.schema.SaltingUtil; @@ -115,6 +122,10 @@ public class SchemaUtil { }; public static final RowKeySchema VAR_BINARY_SCHEMA = new RowKeySchemaBuilder(1).addField(VAR_BINARY_DATUM, false, SortOrder.getDefault()).build(); + public static final String SCHEMA_FOR_DEFAULT_NAMESPACE = "DEFAULT"; + public static final String HBASE_NAMESPACE = "HBASE"; + public static final List<String> NOT_ALLOWED_SCHEMA_LIST = Arrays.asList(SCHEMA_FOR_DEFAULT_NAMESPACE, + HBASE_NAMESPACE); /** * May not be instantiated @@ -236,6 +247,12 @@ public class SchemaUtil { return ByteUtil.concat(tenantId, QueryConstants.SEPARATOR_BYTE_ARRAY, functionName); } + public static byte[] getKeyForSchema(String tenantId, String schemaName) { + return ByteUtil.concat(tenantId == null ? ByteUtil.EMPTY_BYTE_ARRAY : Bytes.toBytes(tenantId), + QueryConstants.SEPARATOR_BYTE_ARRAY, + schemaName == null ? ByteUtil.EMPTY_BYTE_ARRAY : Bytes.toBytes(schemaName)); + } + public static byte[] getTableKey(String tenantId, String schemaName, String tableName) { return ByteUtil.concat(tenantId == null ? ByteUtil.EMPTY_BYTE_ARRAY : Bytes.toBytes(tenantId), QueryConstants.SEPARATOR_BYTE_ARRAY, schemaName == null ? ByteUtil.EMPTY_BYTE_ARRAY : Bytes.toBytes(schemaName), QueryConstants.SEPARATOR_BYTE_ARRAY, Bytes.toBytes(tableName)); } @@ -253,6 +270,11 @@ public class SchemaUtil { return cf + QueryConstants.NAME_SEPARATOR + cq; } + private static String getName(String name, boolean caseSensitive) { + String cq = caseSensitive ? "\"" + name + "\"" : name; + return cq; + } + public static String getTableName(byte[] schemaName, byte[] tableName) { return getName(schemaName, tableName); } @@ -276,9 +298,13 @@ public class SchemaUtil { } return getName(familyName, columnName, false); } + if ((familyName == null || familyName.isEmpty()) && (columnName == null || columnName.isEmpty()) + && (tableName == null || tableName.equals(MetaDataClient.EMPTY_TABLE))) { return getName(schemaName, + false); } if ((familyName == null || familyName.isEmpty()) && (columnName == null || columnName.isEmpty())) { return getName(schemaName, tableName, false); } + return getName(getName(schemaName, tableName, false), getName(familyName, columnName, false), false); } @@ -414,19 +440,24 @@ public class SchemaUtil { } public static boolean isMetaTable(byte[] tableName) { - return Bytes.compareTo(tableName, SYSTEM_CATALOG_NAME_BYTES) == 0; + return Bytes.compareTo(tableName, SYSTEM_CATALOG_NAME_BYTES) == 0 || Bytes.compareTo(tableName, + SchemaUtil.getPhysicalTableName(SYSTEM_CATALOG_NAME_BYTES, true).getName()) == 0; } public static boolean isFunctionTable(byte[] tableName) { - return Bytes.compareTo(tableName, SYSTEM_FUNCTION_NAME_BYTES) == 0; + return Bytes.compareTo(tableName, SYSTEM_FUNCTION_NAME_BYTES) == 0 || Bytes.compareTo(tableName, + SchemaUtil.getPhysicalTableName(SYSTEM_FUNCTION_NAME_BYTES, true).getName()) == 0; } public static boolean isStatsTable(byte[] tableName) { - return Bytes.compareTo(tableName, SYSTEM_STATS_NAME_BYTES) == 0; + return Bytes.compareTo(tableName, SYSTEM_STATS_NAME_BYTES) == 0 || Bytes.compareTo(tableName, + SchemaUtil.getPhysicalTableName(SYSTEM_STATS_NAME_BYTES, true).getName()) == 0; } - + public static boolean isSequenceTable(byte[] tableName) { - return Bytes.compareTo(tableName, PhoenixDatabaseMetaData.SYSTEM_SEQUENCE_NAME_BYTES) == 0; + return Bytes.compareTo(tableName, PhoenixDatabaseMetaData.SYSTEM_SEQUENCE_NAME_BYTES) == 0 + || Bytes.compareTo(tableName, SchemaUtil + .getPhysicalTableName(PhoenixDatabaseMetaData.SYSTEM_SEQUENCE_NAME_BYTES, true).getName()) == 0; } public static boolean isSequenceTable(PTable table) { @@ -564,9 +595,15 @@ public class SchemaUtil { return true; } } - + public static String getSchemaNameFromFullName(String tableName) { - int index = tableName.indexOf(QueryConstants.NAME_SEPARATOR); + if (tableName + .contains(":")) { return getSchemaNameFromFullName(tableName, QueryConstants.NAMESPACE_SEPARATOR); } + return getSchemaNameFromFullName(tableName, QueryConstants.NAME_SEPARATOR); + } + + public static String getSchemaNameFromFullName(String tableName, String separator) { + int index = tableName.indexOf(separator); if (index < 0) { return StringUtil.EMPTY_STRING; } @@ -588,7 +625,8 @@ public class SchemaUtil { } int index = indexOf(tableName, QueryConstants.NAME_SEPARATOR_BYTE); if (index < 0) { - return StringUtil.EMPTY_STRING; + index = indexOf(tableName, QueryConstants.NAMESPACE_SEPARATOR_BYTE); + if (index < 0) { return StringUtil.EMPTY_STRING; } } return Bytes.toString(tableName, 0, index); } @@ -599,13 +637,19 @@ public class SchemaUtil { } int index = indexOf(tableName, QueryConstants.NAME_SEPARATOR_BYTE); if (index < 0) { - return Bytes.toString(tableName); + index = indexOf(tableName, QueryConstants.NAMESPACE_SEPARATOR_BYTE); + if (index < 0) { return Bytes.toString(tableName); } } return Bytes.toString(tableName, index+1, tableName.length - index - 1); } public static String getTableNameFromFullName(String tableName) { - int index = tableName.indexOf(QueryConstants.NAME_SEPARATOR); + if (tableName.contains(":")) { return getTableNameFromFullName(tableName, QueryConstants.NAMESPACE_SEPARATOR); } + return getTableNameFromFullName(tableName, QueryConstants.NAME_SEPARATOR); + } + + public static String getTableNameFromFullName(String tableName, String separator) { + int index = tableName.indexOf(separator); if (index < 0) { return tableName; } @@ -615,7 +659,8 @@ public class SchemaUtil { public static byte[] getTableKeyFromFullName(String fullTableName) { int index = fullTableName.indexOf(QueryConstants.NAME_SEPARATOR); if (index < 0) { - return getTableKey(null, null, fullTableName); + index = fullTableName.indexOf(QueryConstants.NAMESPACE_SEPARATOR); + if (index < 0) { return getTableKey(null, null, fullTableName); } } String schemaName = fullTableName.substring(0, index); String tableName = fullTableName.substring(index+1); @@ -897,4 +942,78 @@ public class SchemaUtil { PName schemaName = dataTable.getSchemaName(); return getTableKey(tenantId == null ? ByteUtil.EMPTY_BYTE_ARRAY : tenantId.getBytes(), schemaName == null ? ByteUtil.EMPTY_BYTE_ARRAY : schemaName.getBytes(), dataTable.getTableName().getBytes()); } + + public static byte[] getSchemaKey(String schemaName) { + return SchemaUtil.getTableKey(null, schemaName, MetaDataClient.EMPTY_TABLE); + } + + public static PName getPhysicalHBaseTableName(PName pName, boolean isNamespaceMapped, PTableType type) { + return getPhysicalHBaseTableName(pName.toString(), isNamespaceMapped, type); + } + + public static PName getPhysicalHBaseTableName(byte[] tableName, boolean isNamespaceMapped, PTableType type) { + return getPhysicalHBaseTableName(Bytes.toString(tableName), isNamespaceMapped, type); + } + + public static TableName getPhysicalTableName(String fullTableName, ReadOnlyProps readOnlyProps) { + return getPhysicalName(Bytes.toBytes(fullTableName), readOnlyProps); + } + + public static TableName getPhysicalTableName(byte[] fullTableName, Configuration conf) { + return getPhysicalTableName(fullTableName, isNamespaceMappingEnabled( + isSystemTable(fullTableName) ? PTableType.SYSTEM : null, new ReadOnlyProps(conf.iterator()))); + } + + public static TableName getPhysicalName(byte[] fullTableName, ReadOnlyProps readOnlyProps) { + return getPhysicalTableName(fullTableName, + isNamespaceMappingEnabled(isSystemTable(fullTableName) ? PTableType.SYSTEM : null, readOnlyProps)); + } + + public static TableName getPhysicalTableName(byte[] fullTableName, boolean isNamespaceMappingEnabled) { + if (indexOf(fullTableName, QueryConstants.NAMESPACE_SEPARATOR_BYTE) > 0 + || !isNamespaceMappingEnabled) { return TableName.valueOf(fullTableName); } + String tableName = getTableNameFromFullName(fullTableName); + String schemaName = getSchemaNameFromFullName(fullTableName); + return TableName.valueOf(schemaName, tableName); + } + + public static PName getPhysicalHBaseTableName(String tableName, boolean isNamespaceMapped, PTableType type) { + if (!isNamespaceMapped) { return PNameFactory.newName(tableName); } + return PNameFactory + .newName(tableName.replace(QueryConstants.NAME_SEPARATOR, QueryConstants.NAMESPACE_SEPARATOR)); + } + + public static boolean isSchemaCheckRequired(PTableType tableType, ReadOnlyProps props) { + return PTableType.TABLE.equals(tableType) && isNamespaceMappingEnabled(tableType, props); + } + + public static boolean isNamespaceMappingEnabled(PTableType type, ReadOnlyProps readOnlyProps) { + return readOnlyProps.getBoolean(QueryServices.IS_NAMESPACE_MAPPING_ENABLED, + QueryServicesOptions.DEFAULT_IS_NAMESPACE_MAPPING_ENABLED) + && (type == null || !PTableType.SYSTEM.equals(type) + || readOnlyProps.getBoolean(QueryServices.IS_SYSTEM_TABLE_MAPPED_TO_NAMESPACE, + QueryServicesOptions.DEFAULT_IS_SYSTEM_TABLE_MAPPED_TO_NAMESPACE)); + } + + public static byte[] getParentTableNameFromIndexTable(byte[] physicalTableName, String indexPrefix) { + String tableName = Bytes.toString(physicalTableName); + return getParentTableNameFromIndexTable(tableName, indexPrefix).getBytes(); + } + + public static String getParentTableNameFromIndexTable(String physicalTableName, String indexPrefix) { + if (physicalTableName.contains(QueryConstants.NAMESPACE_SEPARATOR)) { + String schemaNameFromFullName = getSchemaNameFromFullName(physicalTableName, + QueryConstants.NAMESPACE_SEPARATOR); + String tableNameFromFullName = getTableNameFromFullName(physicalTableName, + QueryConstants.NAMESPACE_SEPARATOR); + return schemaNameFromFullName + QueryConstants.NAMESPACE_SEPARATOR + + getStrippedName(tableNameFromFullName, indexPrefix); + } + return getStrippedName(physicalTableName, indexPrefix); + } + + private static String getStrippedName(String physicalTableName, String indexPrefix) { + return physicalTableName.indexOf(indexPrefix) == 0 ? physicalTableName.substring(indexPrefix.length()) + : physicalTableName; + } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/7e432be7/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 de1a2c7..b82e0c1 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 @@ -28,8 +28,11 @@ import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.LINK_TYPE; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.ORDINAL_POSITION; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SORT_ORDER; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME; +import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_CATALOG_SCHEMA; +import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_CATALOG_TABLE; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_NAME; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_SCHEM; +import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_SEQ_NUM; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TENANT_ID; import static org.apache.phoenix.query.QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT; import static org.apache.phoenix.query.QueryConstants.DIVERGED_VIEW_BASE_COLUMN_COUNT; @@ -67,12 +70,17 @@ import org.apache.hadoop.hbase.client.Put; import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.ResultScanner; import org.apache.hadoop.hbase.client.Scan; +import org.apache.hadoop.hbase.snapshot.SnapshotCreationException; import org.apache.hadoop.hbase.util.Bytes; import org.apache.phoenix.coprocessor.MetaDataEndpointImpl; import org.apache.phoenix.coprocessor.MetaDataProtocol; +import org.apache.phoenix.coprocessor.MetaDataProtocol.MetaDataMutationResult; +import org.apache.phoenix.coprocessor.MetaDataProtocol.MutationCode; import org.apache.phoenix.jdbc.PhoenixConnection; import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData; import org.apache.phoenix.query.QueryConstants; +import org.apache.phoenix.query.QueryServices; +import org.apache.phoenix.schema.MetaDataClient; import org.apache.phoenix.schema.PName; import org.apache.phoenix.schema.PNameFactory; import org.apache.phoenix.schema.PTable; @@ -81,6 +89,7 @@ import org.apache.phoenix.schema.PTable.LinkType; import org.apache.phoenix.schema.PTableType; import org.apache.phoenix.schema.SaltingUtil; import org.apache.phoenix.schema.SortOrder; +import org.apache.phoenix.schema.TableNotFoundException; import org.apache.phoenix.schema.types.PBinary; import org.apache.phoenix.schema.types.PBoolean; import org.apache.phoenix.schema.types.PChar; @@ -124,6 +133,22 @@ public class UpgradeUtil { + "TABLE_NAME = ? " ; + private static final String UPDATE_LINK = + "UPSERT INTO " + SYSTEM_CATALOG_SCHEMA + ".\"" + SYSTEM_CATALOG_TABLE + "\"( " + + TENANT_ID + "," + + TABLE_SCHEM + "," + + TABLE_NAME + "," + + COLUMN_FAMILY + "," + + LINK_TYPE + "," + + TABLE_SEQ_NUM + + ") SELECT " + TENANT_ID + "," + TABLE_SCHEM + "," + TABLE_NAME + ",'%s' AS " + + COLUMN_FAMILY + " ," + LINK_TYPE + "," + TABLE_SEQ_NUM + " FROM " + SYSTEM_CATALOG_SCHEMA + ".\"" + + SYSTEM_CATALOG_TABLE + "\" WHERE " + COLUMN_FAMILY + "=? AND " + LINK_TYPE + " = " + + LinkType.PHYSICAL_TABLE.getSerializedValue(); + + private static final String DELETE_LINK = "DELETE FROM " + SYSTEM_CATALOG_SCHEMA + "." + SYSTEM_CATALOG_TABLE + + " WHERE " + COLUMN_FAMILY + "=? AND " + LINK_TYPE + " = " + LinkType.PHYSICAL_TABLE.getSerializedValue(); + private UpgradeUtil() { } @@ -1279,4 +1304,156 @@ public class UpgradeUtil { } return false; } + + private static void mapTableToNamespace(HBaseAdmin admin, HTableInterface metatable, String srcTableName, + String destTableName, ReadOnlyProps props, Long ts, String phoenixTableName, PTableType pTableType) + throws SnapshotCreationException, IllegalArgumentException, IOException, InterruptedException, + SQLException { + srcTableName = SchemaUtil.normalizeIdentifier(srcTableName); + if (!SchemaUtil.isNamespaceMappingEnabled(pTableType, + props)) { throw new IllegalArgumentException(SchemaUtil.isSystemTable(srcTableName.getBytes()) + ? "For system table " + QueryServices.IS_SYSTEM_TABLE_MAPPED_TO_NAMESPACE + + " also needs to be enabled along with " + QueryServices.IS_NAMESPACE_MAPPING_ENABLED + : QueryServices.IS_NAMESPACE_MAPPING_ENABLED + " is not enabled"); } + // we need to move physical table in actual namespace for TABLE and Index + if (admin.tableExists(srcTableName) && (PTableType.TABLE.equals(pTableType) + || PTableType.INDEX.equals(pTableType) || PTableType.SYSTEM.equals(pTableType))) { + String snapshotName = QueryConstants.UPGRADE_TABLE_SNAPSHOT_PREFIX + srcTableName; + logger.info("Disabling table " + srcTableName + " .."); + admin.disableTable(srcTableName); + logger.info(String.format("Taking snapshot %s of table %s..", snapshotName, srcTableName)); + admin.snapshot(snapshotName, srcTableName); + logger.info(String.format("Restoring snapshot %s in destination table %s..", snapshotName, destTableName)); + admin.cloneSnapshot(Bytes.toBytes(snapshotName), Bytes.toBytes(destTableName)); + logger.info(String.format("deleting old table %s..", srcTableName)); + admin.deleteTable(srcTableName); + logger.info(String.format("deleting snapshot %s..", snapshotName)); + admin.deleteSnapshot(snapshotName); + } + // Update flag to represent table is mapped to namespace + logger.info(String.format("Updating meta information of phoenix table '%s' to map to namespace..", phoenixTableName)); + Put put = new Put(SchemaUtil.getTableKey(null, SchemaUtil.getSchemaNameFromFullName(phoenixTableName), + SchemaUtil.getTableNameFromFullName(phoenixTableName)), ts); + put.add(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, PhoenixDatabaseMetaData.IS_NAMESPACE_MAPPED_BYTES, + PBoolean.INSTANCE.toBytes(Boolean.TRUE)); + metatable.put(put); + } + + /* + * Method to map existing phoenix table to a namespace. Should not be use if tables has views and indexes ,instead + * use map table utility in psql.py + */ + public static void mapTableToNamespace(HBaseAdmin admin, HTableInterface metatable, String tableName, + ReadOnlyProps props, Long ts, PTableType pTableType) throws SnapshotCreationException, + IllegalArgumentException, IOException, InterruptedException, SQLException { + String destTablename = SchemaUtil + .normalizeIdentifier(SchemaUtil.getPhysicalTableName(tableName, props).getNameAsString()); + mapTableToNamespace(admin, metatable, tableName, destTablename, props, ts, tableName, pTableType); + } + + public static void upgradeTable(PhoenixConnection conn, String srcTable) throws SQLException, + SnapshotCreationException, IllegalArgumentException, IOException, InterruptedException { + ReadOnlyProps readOnlyProps = conn.getQueryServices().getProps(); + if (conn.getClientInfo(PhoenixRuntime.TENANT_ID_ATTRIB) != null) { throw new SQLException( + "May not specify the TENANT_ID_ATTRIB property when upgrading"); } + if (conn.getSchema() != null) { throw new IllegalArgumentException( + "Schema should not be set for connection!!"); } + try (HBaseAdmin admin = conn.getQueryServices().getAdmin(); + HTableInterface metatable = conn.getQueryServices() + .getTable(SchemaUtil + .getPhysicalName(PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME_BYTES, readOnlyProps) + .getName());) { + String tableName = SchemaUtil.normalizeIdentifier(srcTable); + String schemaName = SchemaUtil.getSchemaNameFromFullName(tableName); + + // Upgrade is not required if schemaName is not present. + if (schemaName.equals("")) { throw new IllegalArgumentException("Table doesn't have schema name"); } + + // Confirm table is not already upgraded + PTable table = PhoenixRuntime.getTable(conn, tableName); + if (table.isNamespaceMapped()) { throw new IllegalArgumentException("Table is already upgraded"); } + logger.info(String.format("Creating schema %s..", schemaName)); + conn.createStatement().execute("CREATE SCHEMA IF NOT EXISTS " + schemaName); + String newPhysicalTablename = SchemaUtil.normalizeIdentifier(SchemaUtil + .getPhysicalTableName(table.getPhysicalName().getString(), readOnlyProps).getNameAsString()); + logger.info(String.format("Upgrading %s %s..", table.getType(), tableName)); + // Upgrade the data or main table + mapTableToNamespace(admin, metatable, tableName, newPhysicalTablename, readOnlyProps, + PhoenixRuntime.getCurrentScn(readOnlyProps), tableName, table.getType()); + + // clear the cache and get new table + conn.getQueryServices().clearTableFromCache(ByteUtil.EMPTY_BYTE_ARRAY, table.getSchemaName().getBytes(), + table.getTableName().getBytes(), PhoenixRuntime.getCurrentScn(readOnlyProps)); + MetaDataMutationResult result = new MetaDataClient(conn).updateCache(schemaName, + SchemaUtil.getTableNameFromFullName(tableName)); + if (result.getMutationCode() != MutationCode.TABLE_ALREADY_EXISTS) { throw new TableNotFoundException( + tableName); } + table = result.getTable(); + // check whether table is properly upgraded before upgrading indexes + if (table.isNamespaceMapped()) { + for (PTable index : table.getIndexes()) { + String srcTableName = index.getPhysicalName().getString(); + if (srcTableName.contains(QueryConstants.NAMESPACE_SEPARATOR) + || (!MetaDataUtil.isViewIndex(srcTableName) && PTableType.VIEW.equals(table.getType()))) { + // this condition occurs in case of multiple views on same table + // as all view indexes uses the same physical table, so if one view is already migrated then we + // can skip migrating the physical table again + logger.info(String.format("skipping as it seems index '%s' is already upgraded..", index.getName())); + continue; + } + String destTableName = null; + String phoenixTableName = index.getName().getString(); + boolean updateLink = false; + if (MetaDataUtil.isLocalIndex(srcTableName)) { + logger.info(String.format("local index '%s' found with physical hbase table name ''..", + index.getName(), srcTableName)); + destTableName = Bytes + .toString(MetaDataUtil.getLocalIndexPhysicalName(newPhysicalTablename.getBytes())); + // update parent_table property in local index table descriptor + conn.createStatement() + .execute(String.format("ALTER TABLE %s set " + MetaDataUtil.PARENT_TABLE_KEY + "='%s'", + phoenixTableName, table.getPhysicalName())); + updateLink = true; + } else if (MetaDataUtil.isViewIndex(srcTableName)) { + logger.info(String.format("View index '%s' found with physical hbase table name ''..", + index.getName(), srcTableName)); + destTableName = Bytes + .toString(MetaDataUtil.getViewIndexPhysicalName(newPhysicalTablename.getBytes())); + updateLink = true; + } else { + logger.info(String.format("Global index '%s' found with physical hbase table name ''..", + index.getName(), srcTableName)); + destTableName = SchemaUtil + .getPhysicalTableName(index.getPhysicalName().getString(), readOnlyProps) + .getNameAsString(); + } + logger.info(String.format("Upgrading index %s..", index.getName())); + mapTableToNamespace(admin, metatable, srcTableName, destTableName, readOnlyProps, + PhoenixRuntime.getCurrentScn(readOnlyProps), phoenixTableName, index.getType()); + if (updateLink) { + logger.info(String.format("Updating link information for index '%s' ..", index.getName())); + updateLink(conn, srcTableName, destTableName); + } + conn.getQueryServices().clearTableFromCache(ByteUtil.EMPTY_BYTE_ARRAY, + index.getSchemaName().getBytes(), index.getTableName().getBytes(), + PhoenixRuntime.getCurrentScn(readOnlyProps)); + } + + } else { + throw new RuntimeException("Error: problem occured during upgrade. Table is not upgraded successfully"); + } + } + } + + private static void updateLink(PhoenixConnection conn, String srcTableName, String destTableName) + throws SQLException { + PreparedStatement deleteLinkStatment = conn.prepareStatement(DELETE_LINK); + deleteLinkStatment.setString(1, srcTableName); + PreparedStatement updateLinkStatment = conn.prepareStatement(String.format(UPDATE_LINK, destTableName)); + updateLinkStatment.setString(1, srcTableName); + deleteLinkStatment.execute(); + updateLinkStatment.execute(); + conn.commit(); + } + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/phoenix/blob/7e432be7/phoenix-core/src/test/java/org/apache/phoenix/execute/CorrelatePlanTest.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/test/java/org/apache/phoenix/execute/CorrelatePlanTest.java b/phoenix-core/src/test/java/org/apache/phoenix/execute/CorrelatePlanTest.java index 6d0930d..4660e38 100644 --- a/phoenix-core/src/test/java/org/apache/phoenix/execute/CorrelatePlanTest.java +++ b/phoenix-core/src/test/java/org/apache/phoenix/execute/CorrelatePlanTest.java @@ -256,7 +256,7 @@ public class CorrelatePlanTest { PTableType.SUBQUERY, null, MetaDataProtocol.MIN_TABLE_TIMESTAMP, PTable.INITIAL_SEQ_NUM, null, null, columns, null, null, Collections.<PTable>emptyList(), false, Collections.<PName>emptyList(), null, null, false, false, false, null, - null, null, true, false, 0, 0L); + null, null, true, false, 0, 0L, Boolean.FALSE); TableRef sourceTable = new TableRef(pTable); List<ColumnRef> sourceColumnRefs = Lists.<ColumnRef> newArrayList(); for (PColumn column : sourceTable.getTable().getColumns()) { http://git-wip-us.apache.org/repos/asf/phoenix/blob/7e432be7/phoenix-core/src/test/java/org/apache/phoenix/execute/LiteralResultIteratorPlanTest.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/test/java/org/apache/phoenix/execute/LiteralResultIteratorPlanTest.java b/phoenix-core/src/test/java/org/apache/phoenix/execute/LiteralResultIteratorPlanTest.java index 8ecf0ee..aba4be4 100644 --- a/phoenix-core/src/test/java/org/apache/phoenix/execute/LiteralResultIteratorPlanTest.java +++ b/phoenix-core/src/test/java/org/apache/phoenix/execute/LiteralResultIteratorPlanTest.java @@ -177,7 +177,7 @@ public class LiteralResultIteratorPlanTest { PTable pTable = PTableImpl.makePTable(null, PName.EMPTY_NAME, PName.EMPTY_NAME, PTableType.SUBQUERY, null, MetaDataProtocol.MIN_TABLE_TIMESTAMP, PTable.INITIAL_SEQ_NUM, null, null, columns, null, null, Collections.<PTable> emptyList(), false, Collections.<PName> emptyList(), null, null, false, false, - false, null, null, null, true, false, 0, 0L); + false, null, null, null, true, false, 0, 0L, false); TableRef sourceTable = new TableRef(pTable); List<ColumnRef> sourceColumnRefs = Lists.<ColumnRef> newArrayList(); for (PColumn column : sourceTable.getTable().getColumns()) { http://git-wip-us.apache.org/repos/asf/phoenix/blob/7e432be7/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java b/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java index e3bd4a0..d8651ae 100644 --- a/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java +++ b/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java @@ -118,9 +118,7 @@ import java.util.concurrent.TimeoutException; import javax.annotation.Nonnull; - import org.apache.commons.lang.RandomStringUtils; - import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.HBaseTestingUtility; @@ -128,7 +126,6 @@ import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.IntegrationTestingUtility; -import org.apache.hadoop.hbase.RandomStringGeneratorImpl; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.HBaseAdmin; import org.apache.hadoop.hbase.coprocessor.CoprocessorHost; @@ -147,6 +144,7 @@ import org.apache.phoenix.exception.SQLExceptionCode; import org.apache.phoenix.exception.SQLExceptionInfo; import org.apache.phoenix.hbase.index.balancer.IndexLoadBalancer; import org.apache.phoenix.hbase.index.master.IndexMasterObserver; +import org.apache.phoenix.jdbc.PhoenixConnection; import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData; import org.apache.phoenix.jdbc.PhoenixDriver; import org.apache.phoenix.jdbc.PhoenixEmbeddedDriver; @@ -829,6 +827,7 @@ public abstract class BaseTest { protected static void ensureTableCreated(String url, String tableName, byte[][] splits, Long ts) throws SQLException { String ddl = tableDDLMap.get(tableName); + createSchema(url,tableName, ts); createTestTable(url, ddl, splits, ts); } @@ -843,7 +842,23 @@ public abstract class BaseTest { protected static void createTestTable(String url, String ddl, byte[][] splits, Long ts) throws SQLException { createTestTable(url, ddl, splits, ts, true); } - + + public static void createSchema(String url, String tableName, Long ts) throws SQLException { + String schema = SchemaUtil.getSchemaNameFromFullName(tableName); + if (!schema.equals("")) { + Properties props = new Properties(); + if (ts != null) { + props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts)); + } + try (Connection conn = DriverManager.getConnection(url, props);) { + if (SchemaUtil.isNamespaceMappingEnabled(null, + conn.unwrap(PhoenixConnection.class).getQueryServices().getProps())) { + conn.createStatement().executeUpdate("CREATE SCHEMA IF NOT EXISTS " + schema); + } + } + } + } + protected static void createTestTable(String url, String ddl, byte[][] splits, Long ts, boolean swallowTableAlreadyExistsException) throws SQLException { assertNotNull(ddl); StringBuilder buf = new StringBuilder(ddl); http://git-wip-us.apache.org/repos/asf/phoenix/blob/7e432be7/phoenix-core/src/test/java/org/apache/phoenix/query/ParallelIteratorsSplitTest.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/test/java/org/apache/phoenix/query/ParallelIteratorsSplitTest.java b/phoenix-core/src/test/java/org/apache/phoenix/query/ParallelIteratorsSplitTest.java index ff06ff9..47101b2 100644 --- a/phoenix-core/src/test/java/org/apache/phoenix/query/ParallelIteratorsSplitTest.java +++ b/phoenix-core/src/test/java/org/apache/phoenix/query/ParallelIteratorsSplitTest.java @@ -54,6 +54,7 @@ import org.apache.phoenix.jdbc.PhoenixStatement; import org.apache.phoenix.jdbc.PhoenixStatement.Operation; import org.apache.phoenix.parse.FilterableStatement; import org.apache.phoenix.parse.PFunction; +import org.apache.phoenix.parse.PSchema; import org.apache.phoenix.parse.SelectStatement; import org.apache.phoenix.schema.ColumnRef; import org.apache.phoenix.schema.PDatum; @@ -348,6 +349,16 @@ public class ParallelIteratorsSplitTest extends BaseConnectionlessQueryTest { public boolean hasUDFs() { return false; } + + @Override + public PSchema resolveSchema(String schemaName) throws SQLException { + return null; + } + + @Override + public List<PSchema> getSchemas() { + return null; + } }; PhoenixConnection connection = DriverManager.getConnection(getUrl(), PropertiesUtil.deepCopy(TEST_PROPERTIES)).unwrap(PhoenixConnection.class); final PhoenixStatement statement = new PhoenixStatement(connection); http://git-wip-us.apache.org/repos/asf/phoenix/blob/7e432be7/phoenix-core/src/test/java/org/apache/phoenix/util/JDBCUtilTest.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/test/java/org/apache/phoenix/util/JDBCUtilTest.java b/phoenix-core/src/test/java/org/apache/phoenix/util/JDBCUtilTest.java index 74b397f..8c270c3 100644 --- a/phoenix-core/src/test/java/org/apache/phoenix/util/JDBCUtilTest.java +++ b/phoenix-core/src/test/java/org/apache/phoenix/util/JDBCUtilTest.java @@ -21,6 +21,7 @@ import static org.apache.phoenix.util.PhoenixRuntime.ANNOTATION_ATTRIB_PREFIX; import static org.apache.phoenix.util.PhoenixRuntime.TENANT_ID_ATTRIB; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.util.Map; @@ -89,6 +90,13 @@ public class JDBCUtilTest { } @Test + public void testSchema() { + assertTrue(JDBCUtil.getSchema("localhost;schema=TEST", new Properties(), null).equals("TEST")); + assertNull(JDBCUtil.getSchema("localhost;schema=", new Properties(), null)); + assertNull(JDBCUtil.getSchema("localhost;", new Properties(), null)); + } + + @Test public void testGetAutoCommit_TrueInProperties() { Properties props = new Properties(); props.setProperty("AutoCommit", "true"); http://git-wip-us.apache.org/repos/asf/phoenix/blob/7e432be7/phoenix-protocol/src/main/MetaDataService.proto ---------------------------------------------------------------------- diff --git a/phoenix-protocol/src/main/MetaDataService.proto b/phoenix-protocol/src/main/MetaDataService.proto index d1dcf9a..9d7b209 100644 --- a/phoenix-protocol/src/main/MetaDataService.proto +++ b/phoenix-protocol/src/main/MetaDataService.proto @@ -26,6 +26,7 @@ option optimize_for = SPEED; import "PTable.proto"; import "PFunction.proto"; +import "PSchema.proto"; enum MutationCode { TABLE_ALREADY_EXISTS = 0; @@ -42,6 +43,12 @@ enum MutationCode { FUNCTION_NOT_FOUND = 11; NEWER_FUNCTION_FOUND = 12; FUNCTION_NOT_IN_REGION = 13; + SCHEMA_ALREADY_EXISTS = 14; + NEWER_SCHEMA_FOUND = 15; + SCHEMA_NOT_FOUND = 16; + SCHEMA_NOT_IN_REGION = 17; + TABLES_EXIST_ON_SCHEMA = 18; + UNALLOWED_SCHEMA_MUTATION = 19; }; message SharedTableState { @@ -63,6 +70,7 @@ message MetaDataResponse { optional bytes functionName = 7; repeated PFunction function = 8; repeated SharedTableState sharedTablesToDelete = 9; + optional PSchema schema = 10; } message GetTableRequest { @@ -82,6 +90,12 @@ message GetFunctionsRequest { optional int32 clientVersion = 5; } +message GetSchemaRequest { + required string schemaName = 1; + required int64 clientTimestamp = 2; + required int32 clientVersion = 3; +} + // each byte array represents a MutationProto instance message CreateTableRequest { repeated bytes tableMetadataMutations = 1; @@ -96,6 +110,12 @@ message CreateFunctionRequest { optional int32 clientVersion = 4; } +message CreateSchemaRequest { + repeated bytes tableMetadataMutations = 1; + required string schemaName = 2; + required int32 clientVersion = 3; +} + message DropTableRequest { repeated bytes tableMetadataMutations = 1; required string tableType = 2; @@ -103,6 +123,12 @@ message DropTableRequest { optional int32 clientVersion = 4; } +message DropSchemaRequest { + repeated bytes schemaMetadataMutations = 1; + required string schemaName = 2; + required int32 clientVersion = 3; +} + message AddColumnRequest { repeated bytes tableMetadataMutations = 1; optional int32 clientVersion = 2; @@ -158,15 +184,24 @@ service MetaDataService { rpc getFunctions(GetFunctionsRequest) returns (MetaDataResponse); + rpc getSchema(GetSchemaRequest) + returns (MetaDataResponse); + rpc createTable(CreateTableRequest) returns (MetaDataResponse); rpc createFunction(CreateFunctionRequest) returns (MetaDataResponse); - + + rpc createSchema(CreateSchemaRequest) + returns (MetaDataResponse); + rpc dropTable(DropTableRequest) returns (MetaDataResponse); - + + rpc dropSchema(DropSchemaRequest) + returns (MetaDataResponse); + rpc dropFunction(DropFunctionRequest) returns (MetaDataResponse); http://git-wip-us.apache.org/repos/asf/phoenix/blob/7e432be7/phoenix-protocol/src/main/PSchema.proto ---------------------------------------------------------------------- diff --git a/phoenix-protocol/src/main/PSchema.proto b/phoenix-protocol/src/main/PSchema.proto new file mode 100644 index 0000000..91e12f59 --- /dev/null +++ b/phoenix-protocol/src/main/PSchema.proto @@ -0,0 +1,30 @@ +/* + * Copyright 2010 The Apache Software Foundation + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +option java_package = "org.apache.phoenix.coprocessor.generated"; +option java_outer_classname = "PSchemaProtos"; +option java_generic_services = true; +option java_generate_equals_and_hash = true; +option optimize_for = SPEED; + +message PSchema { + required string schemaName = 1; + required int64 timeStamp = 2; +} http://git-wip-us.apache.org/repos/asf/phoenix/blob/7e432be7/phoenix-protocol/src/main/PTable.proto ---------------------------------------------------------------------- diff --git a/phoenix-protocol/src/main/PTable.proto b/phoenix-protocol/src/main/PTable.proto index 09bdeb6..c86f6b6 100644 --- a/phoenix-protocol/src/main/PTable.proto +++ b/phoenix-protocol/src/main/PTable.proto @@ -90,4 +90,5 @@ message PTable { optional bool transactional = 27; optional int64 updateCacheFrequency = 28; optional int64 indexDisableTimestamp = 29; + optional bool isNamespaceMapped = 30; }