http://git-wip-us.apache.org/repos/asf/phoenix/blob/4d6dbf9c/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewIT.java index 34292ba..fdfd75b 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewIT.java @@ -28,172 +28,119 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.io.IOException; +import java.math.BigDecimal; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Properties; +import org.apache.curator.shaded.com.google.common.collect.Lists; +import org.apache.hadoop.hbase.DoNotRetryIOException; import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.HBaseAdmin; +import org.apache.hadoop.hbase.client.Mutation; +import org.apache.hadoop.hbase.client.Scan; +import org.apache.hadoop.hbase.coprocessor.ObserverContext; +import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment; +import org.apache.hadoop.hbase.coprocessor.SimpleRegionObserver; +import org.apache.hadoop.hbase.regionserver.MiniBatchOperationInProgress; +import org.apache.hadoop.hbase.util.Bytes; +import org.apache.hadoop.hbase.util.Pair; import org.apache.phoenix.compile.QueryPlan; +import org.apache.phoenix.exception.PhoenixIOException; import org.apache.phoenix.exception.SQLExceptionCode; import org.apache.phoenix.jdbc.PhoenixConnection; +import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData; +import org.apache.phoenix.jdbc.PhoenixStatement; import org.apache.phoenix.query.KeyRange; import org.apache.phoenix.query.QueryServices; import org.apache.phoenix.schema.ColumnAlreadyExistsException; +import org.apache.phoenix.schema.PColumn; +import org.apache.phoenix.schema.PTable; +import org.apache.phoenix.schema.PTableType; import org.apache.phoenix.schema.ReadOnlyTableException; import org.apache.phoenix.schema.TableNotFoundException; +import org.apache.phoenix.util.MetaDataUtil; import org.apache.phoenix.util.PhoenixRuntime; import org.apache.phoenix.util.QueryUtil; +import org.apache.phoenix.util.ReadOnlyProps; import org.apache.phoenix.util.SchemaUtil; +import org.apache.phoenix.util.TestUtil; +import org.junit.BeforeClass; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; +import com.google.common.collect.Maps; +@RunWith(Parameterized.class) +public class ViewIT extends SplitSystemCatalogIT { -public class ViewIT extends BaseViewIT { - - public ViewIT(boolean transactional) { - super(transactional); - } - - @Test - public void testReadOnlyOnReadOnlyView() throws Exception { - Connection earlierCon = DriverManager.getConnection(getUrl()); - Connection conn = DriverManager.getConnection(getUrl()); - String ddl = "CREATE TABLE " + fullTableName + " (k INTEGER NOT NULL PRIMARY KEY, v1 DATE) "+ tableDDLOptions; - conn.createStatement().execute(ddl); - String fullParentViewName = "V_" + generateUniqueName(); - ddl = "CREATE VIEW " + fullParentViewName + " (v2 VARCHAR) AS SELECT * FROM " + fullTableName + " WHERE k > 5"; - conn.createStatement().execute(ddl); - try { - conn.createStatement().execute("UPSERT INTO " + fullParentViewName + " VALUES(1)"); - fail(); - } catch (ReadOnlyTableException e) { - - } - for (int i = 0; i < 10; i++) { - conn.createStatement().execute("UPSERT INTO " + fullTableName + " VALUES(" + i + ")"); - } - conn.commit(); - - analyzeTable(conn, fullParentViewName, transactional); - - List<KeyRange> splits = getAllSplits(conn, fullParentViewName); - assertEquals(4, splits.size()); - - int count = 0; - ResultSet rs = conn.createStatement().executeQuery("SELECT k FROM " + fullTableName); - while (rs.next()) { - assertEquals(count++, rs.getInt(1)); - } - assertEquals(10, count); - - count = 0; - rs = conn.createStatement().executeQuery("SELECT k FROM " + fullParentViewName); - while (rs.next()) { - count++; - assertEquals(count + 5, rs.getInt(1)); - } - assertEquals(4, count); - count = 0; - rs = earlierCon.createStatement().executeQuery("SELECT k FROM " + fullParentViewName); - while (rs.next()) { - count++; - assertEquals(count + 5, rs.getInt(1)); - } - assertEquals(4, count); - String fullViewName = "V_" + generateUniqueName(); - ddl = "CREATE VIEW " + fullViewName + " AS SELECT * FROM " + fullParentViewName + " WHERE k < 9"; - conn.createStatement().execute(ddl); - try { - conn.createStatement().execute("UPSERT INTO " + fullViewName + " VALUES(1)"); - fail(); - } catch (ReadOnlyTableException e) { - - } finally { - conn.close(); - } + protected String tableDDLOptions; + protected boolean transactional; - conn = DriverManager.getConnection(getUrl()); - count = 0; - rs = conn.createStatement().executeQuery("SELECT k FROM " + fullViewName); - while (rs.next()) { - count++; - assertEquals(count + 5, rs.getInt(1)); + public ViewIT(boolean transactional) { + StringBuilder optionBuilder = new StringBuilder(); + this.transactional = transactional; + if (transactional) { + optionBuilder.append(" TRANSACTIONAL=true "); } - assertEquals(3, count); + this.tableDDLOptions = optionBuilder.toString(); } - @Test - public void testNonSaltedUpdatableViewWithIndex() throws Exception { - testUpdatableViewWithIndex(null, false); - } - - @Test - public void testNonSaltedUpdatableViewWithLocalIndex() throws Exception { - testUpdatableViewWithIndex(null, true); + @Parameters(name = "transactional = {0}") + public static Collection<Boolean> data() { + return Arrays.asList(new Boolean[] { false, true }); } - @Test - public void testUpdatableOnUpdatableView() throws Exception { - String viewName = testUpdatableView(null); - Connection conn = DriverManager.getConnection(getUrl()); - String fullViewName = "V_" + generateUniqueName(); - String ddl = "CREATE VIEW " + fullViewName + " AS SELECT * FROM " + viewName + " WHERE k3 = 2"; - conn.createStatement().execute(ddl); - ResultSet rs = conn.createStatement().executeQuery("SELECT k1, k2, k3 FROM " + fullViewName); - assertTrue(rs.next()); - assertEquals(1, rs.getInt(1)); - assertEquals(109, rs.getInt(2)); - assertEquals(2, rs.getInt(3)); - assertFalse(rs.next()); - - conn.createStatement().execute("UPSERT INTO " + fullViewName + "(k2) VALUES(122)"); - conn.commit(); - rs = conn.createStatement().executeQuery("SELECT k1, k2, k3 FROM " + fullViewName + " WHERE k2 >= 120"); - assertTrue(rs.next()); - assertEquals(1, rs.getInt(1)); - assertEquals(122, rs.getInt(2)); - assertEquals(2, rs.getInt(3)); - assertFalse(rs.next()); - - try { - conn.createStatement().execute("UPSERT INTO " + fullViewName + "(k2,k3) VALUES(123,3)"); - fail(); - } catch (SQLException e) { - assertEquals(SQLExceptionCode.CANNOT_UPDATE_VIEW_COLUMN.getErrorCode(), e.getErrorCode()); - } - - try { - conn.createStatement().execute("UPSERT INTO " + fullViewName + "(k2,k3) select k2, 3 from " + fullViewName); - fail(); - } catch (SQLException e) { - assertEquals(SQLExceptionCode.CANNOT_UPDATE_VIEW_COLUMN.getErrorCode(), e.getErrorCode()); + @BeforeClass + public static void doSetup() throws Exception { + NUM_SLAVES_BASE = 6; + Map<String, String> props = Collections.emptyMap(); + boolean splitSystemCatalog = (driver == null); + Map<String, String> serverProps = Maps.newHashMapWithExpectedSize(1); + serverProps.put("hbase.coprocessor.region.classes", FailingRegionObserver.class.getName()); + serverProps.put("hbase.coprocessor.abortonerror", "false"); + setUpTestDriver(new ReadOnlyProps(serverProps.entrySet().iterator()), new ReadOnlyProps(props.entrySet().iterator())); + // Split SYSTEM.CATALOG once after the mini-cluster is started + if (splitSystemCatalog) { + splitSystemCatalog(); } } - + @Test public void testReadOnlyOnUpdatableView() throws Exception { - String viewName = testUpdatableView(null); + String fullTableName = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); + String fullViewName1 = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); + String fullViewName2 = SchemaUtil.getTableName(SCHEMA3, generateUniqueName()); + String ddl = + "CREATE VIEW " + fullViewName2 + " AS SELECT * FROM " + fullViewName1 + + " WHERE k3 > 1 and k3 < 50"; + testUpdatableView(fullTableName, fullViewName1, fullViewName2, ddl, null, tableDDLOptions); Connection conn = DriverManager.getConnection(getUrl()); - String fullViewName = "V_" + generateUniqueName(); - String ddl = "CREATE VIEW " + fullViewName + " AS SELECT * FROM " + viewName + " WHERE k3 > 1 and k3 < 50"; - conn.createStatement().execute(ddl); - ResultSet rs = conn.createStatement().executeQuery("SELECT k1, k2, k3 FROM " + fullViewName); + ResultSet rs = conn.createStatement().executeQuery("SELECT k1, k2, k3 FROM " + fullViewName2); assertTrue(rs.next()); assertEquals(1, rs.getInt(1)); assertEquals(109, rs.getInt(2)); assertEquals(2, rs.getInt(3)); assertFalse(rs.next()); - try { - conn.createStatement().execute("UPSERT INTO " + fullViewName + " VALUES(1)"); + conn.createStatement().execute("UPSERT INTO " + fullViewName2 + " VALUES(1)"); fail(); } catch (ReadOnlyTableException e) { @@ -201,22 +148,27 @@ public class ViewIT extends BaseViewIT { conn.createStatement().execute("UPSERT INTO " + fullTableName + "(k1, k2,k3) VALUES(1, 122, 5)"); conn.commit(); - rs = conn.createStatement().executeQuery("SELECT k1, k2, k3 FROM " + fullViewName + " WHERE k2 >= 120"); + rs = conn.createStatement().executeQuery("SELECT k1, k2, k3 FROM " + fullViewName2 + " WHERE k2 >= 120"); assertTrue(rs.next()); assertEquals(1, rs.getInt(1)); assertEquals(122, rs.getInt(2)); assertEquals(5, rs.getInt(3)); assertFalse(rs.next()); } - + @Test public void testDisallowDropOfReferencedColumn() throws Exception { Connection conn = DriverManager.getConnection(getUrl()); + String fullTableName = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); + String fullViewName1 = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); + String fullViewName2 = SchemaUtil.getTableName(SCHEMA3, generateUniqueName()); + String ddl = "CREATE TABLE " + fullTableName + " (k1 INTEGER NOT NULL, k2 INTEGER NOT NULL, v1 DECIMAL, CONSTRAINT pk PRIMARY KEY (k1, k2))" + tableDDLOptions; conn.createStatement().execute(ddl); - String fullViewName1 = "V_" + generateUniqueName(); ddl = "CREATE VIEW " + fullViewName1 + "(v2 VARCHAR, v3 VARCHAR) AS SELECT * FROM " + fullTableName + " WHERE v1 = 1.0"; conn.createStatement().execute(ddl); + ddl = "CREATE VIEW " + fullViewName2 + " AS SELECT * FROM " + fullViewName1 + " WHERE v2 != 'foo'"; + conn.createStatement().execute(ddl); try { conn.createStatement().execute("ALTER VIEW " + fullViewName1 + " DROP COLUMN v1"); @@ -225,10 +177,6 @@ public class ViewIT extends BaseViewIT { assertEquals(SQLExceptionCode.CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode()); } - String fullViewName2 = "V_" + generateUniqueName(); - ddl = "CREATE VIEW " + fullViewName2 + " AS SELECT * FROM " + fullViewName1 + " WHERE v2 != 'foo'"; - conn.createStatement().execute(ddl); - try { conn.createStatement().execute("ALTER VIEW " + fullViewName2 + " DROP COLUMN v1"); fail(); @@ -249,12 +197,16 @@ public class ViewIT extends BaseViewIT { public void testReadOnlyViewWithCaseSensitiveTableNames() throws Exception { Connection earlierCon = DriverManager.getConnection(getUrl()); Connection conn = DriverManager.getConnection(getUrl()); + String schemaName = TestUtil.DEFAULT_SCHEMA_NAME + "_" + generateUniqueName(); String caseSensitiveTableName = "\"t_" + generateUniqueName() + "\"" ; - String ddl = "CREATE TABLE " + caseSensitiveTableName + " (k INTEGER NOT NULL PRIMARY KEY, v1 DATE)" + tableDDLOptions; - conn.createStatement().execute(ddl); + String fullTableName = SchemaUtil.getTableName(schemaName, caseSensitiveTableName); String caseSensitiveViewName = "\"v_" + generateUniqueName() + "\"" ; - ddl = "CREATE VIEW " + caseSensitiveViewName + " (v2 VARCHAR) AS SELECT * FROM " + caseSensitiveTableName + " WHERE k > 5"; + + String ddl = "CREATE TABLE " + fullTableName + " (k INTEGER NOT NULL PRIMARY KEY, v1 DATE)" + tableDDLOptions; conn.createStatement().execute(ddl); + ddl = "CREATE VIEW " + caseSensitiveViewName + " (v2 VARCHAR) AS SELECT * FROM " + fullTableName + " WHERE k > 5"; + conn.createStatement().execute(ddl); + try { conn.createStatement().execute("UPSERT INTO " + caseSensitiveViewName + " VALUES(1)"); fail(); @@ -262,7 +214,7 @@ public class ViewIT extends BaseViewIT { } for (int i = 0; i < 10; i++) { - conn.createStatement().execute("UPSERT INTO " + caseSensitiveTableName + " VALUES(" + i + ")"); + conn.createStatement().execute("UPSERT INTO " + fullTableName + " VALUES(" + i + ")"); } conn.commit(); @@ -285,11 +237,14 @@ public class ViewIT extends BaseViewIT { @Test public void testReadOnlyViewWithCaseSensitiveColumnNames() throws Exception { Connection conn = DriverManager.getConnection(getUrl()); + String fullTableName = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); + String viewName = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); String ddl = "CREATE TABLE " + fullTableName + " (\"k\" INTEGER NOT NULL PRIMARY KEY, \"v1\" INTEGER, \"a\".v2 VARCHAR)" + tableDDLOptions; + conn.createStatement().execute(ddl); - String viewName = "V_" + generateUniqueName(); ddl = "CREATE VIEW " + viewName + " (v VARCHAR) AS SELECT * FROM " + fullTableName + " WHERE \"k\" > 5 and \"v1\" > 1"; conn.createStatement().execute(ddl); + try { conn.createStatement().execute("UPSERT INTO " + viewName + " VALUES(1)"); fail(); @@ -313,11 +268,14 @@ public class ViewIT extends BaseViewIT { @Test public void testViewWithCurrentDate() throws Exception { Connection conn = DriverManager.getConnection(getUrl()); + String fullTableName = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); + String viewName = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); + String ddl = "CREATE TABLE " + fullTableName + " (k INTEGER NOT NULL PRIMARY KEY, v1 INTEGER, v2 DATE)" + tableDDLOptions; conn.createStatement().execute(ddl); - String viewName = "V_" + generateUniqueName(); ddl = "CREATE VIEW " + viewName + " (v VARCHAR) AS SELECT * FROM " + fullTableName + " WHERE v2 > CURRENT_DATE()-5 AND v2 > DATE '2010-01-01'"; conn.createStatement().execute(ddl); + try { conn.createStatement().execute("UPSERT INTO " + viewName + " VALUES(1)"); fail(); @@ -354,27 +312,33 @@ public class ViewIT extends BaseViewIT { Properties props = new Properties(); props.setProperty(QueryServices.IS_NAMESPACE_MAPPING_ENABLED, Boolean.toString(isNamespaceMapped)); Connection conn = DriverManager.getConnection(getUrl(),props); - String schemaName1 = "S_" + generateUniqueName(); + String tableName = "T_" + generateUniqueName(); + String schemaName1 = SCHEMA1; String fullTableName1 = SchemaUtil.getTableName(schemaName1, tableName); + String viewName1 = "V_" + generateUniqueName(); + String viewSchemaName = SCHEMA2; + String fullViewName1 = SchemaUtil.getTableName(viewSchemaName, viewName1); + String viewName2 = "V_" + generateUniqueName(); + String fullViewName2 = SchemaUtil.getTableName(SCHEMA3, viewName1); + if (isNamespaceMapped) { conn.createStatement().execute("CREATE SCHEMA IF NOT EXISTS " + schemaName1); } - String ddl = "CREATE TABLE " + fullTableName1 + " (k INTEGER NOT NULL PRIMARY KEY, v1 DATE)" + tableDDLOptions; + String ddl = "CREATE TABLE " + fullTableName1 + " (k INTEGER NOT NULL PRIMARY KEY, v1 DATE)" + tableDDLOptions; HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin(); conn.createStatement().execute(ddl); assertTrue(admin.tableExists(SchemaUtil.getPhysicalTableName(SchemaUtil.normalizeIdentifier(fullTableName1), conn.unwrap(PhoenixConnection.class).getQueryServices().getProps()))); - String viewName = "V_" + generateUniqueName(); - String viewSchemaName = "S_" + generateUniqueName(); - String fullViewName1 = SchemaUtil.getTableName(viewSchemaName, viewName); + ddl = "CREATE VIEW " + fullViewName1 + " (v2 VARCHAR) AS SELECT * FROM " + fullTableName1 + " WHERE k > 5"; conn.createStatement().execute(ddl); - String fullViewName2 = "V_" + generateUniqueName(); + ddl = "CREATE VIEW " + fullViewName2 + " (v2 VARCHAR) AS SELECT * FROM " + fullTableName1 + " WHERE k > 5"; conn.createStatement().execute(ddl); + conn.createStatement().executeQuery("SELECT * FROM " + fullViewName1); conn.createStatement().executeQuery("SELECT * FROM " + fullViewName2); - ddl = "DROP VIEW " + viewName; + ddl = "DROP VIEW " + viewName1; try { conn.createStatement().execute(ddl); fail(); @@ -389,20 +353,20 @@ public class ViewIT extends BaseViewIT { } catch (TableNotFoundException ignore) { } ddl = "DROP TABLE " + fullTableName1; - validateCannotDropTableWithChildViewsWithoutCascade(conn, fullTableName1); ddl = "DROP VIEW " + fullViewName2; conn.createStatement().execute(ddl); ddl = "DROP TABLE " + fullTableName1; conn.createStatement().execute(ddl); } - + @Test public void testDisallowDropOfColumnOnParentTable() throws Exception { Connection conn = DriverManager.getConnection(getUrl()); + String fullTableName = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); + String viewName = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); String ddl = "CREATE TABLE " + fullTableName + " (k1 INTEGER NOT NULL, k2 INTEGER NOT NULL, v1 DECIMAL, CONSTRAINT pk PRIMARY KEY (k1, k2))" + tableDDLOptions; conn.createStatement().execute(ddl); - String viewName = "V_" + generateUniqueName(); ddl = "CREATE VIEW " + viewName + "(v2 VARCHAR, v3 VARCHAR) AS SELECT * FROM " + fullTableName + " WHERE v1 = 1.0"; conn.createStatement().execute(ddl); @@ -416,46 +380,171 @@ public class ViewIT extends BaseViewIT { @Test public void testViewAndTableAndDropCascade() throws Exception { - // Setup Connection conn = DriverManager.getConnection(getUrl()); - String ddl = "CREATE TABLE " + fullTableName + " (k INTEGER NOT NULL PRIMARY KEY, v1 DATE)" + tableDDLOptions; - conn.createStatement().execute(ddl); - String viewName = "V_" + generateUniqueName(); - String viewSchemaName = "S_" + generateUniqueName(); - String fullViewName1 = SchemaUtil.getTableName(viewSchemaName, viewName); - ddl = "CREATE VIEW " + fullViewName1 + " (v2 VARCHAR) AS SELECT * FROM " + fullTableName + " WHERE k > 5"; + String fullTableName = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); + String fullViewName1 = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); + String fullViewName2 = SchemaUtil.getTableName(SCHEMA3, generateUniqueName()); + + String tableDdl = "CREATE TABLE " + fullTableName + " (k INTEGER NOT NULL PRIMARY KEY, v1 DATE)" + tableDDLOptions; + conn.createStatement().execute(tableDdl); + String ddl = "CREATE VIEW " + fullViewName1 + " (v2 VARCHAR) AS SELECT * FROM " + fullTableName + " WHERE k > 5"; conn.createStatement().execute(ddl); - ddl = "CREATE LOCAL INDEX idx on " + fullViewName1 + "(v2)"; + String indexName = generateUniqueName(); + ddl = "CREATE LOCAL INDEX " + indexName + " on " + fullViewName1 + "(v2)"; conn.createStatement().execute(ddl); - String fullViewName2 = SchemaUtil.getTableName(viewSchemaName, "V_" + generateUniqueName()); ddl = "CREATE VIEW " + fullViewName2 + "(v2 VARCHAR) AS SELECT * FROM " + fullTableName + " WHERE k > 10"; conn.createStatement().execute(ddl); + + // dropping base table without cascade should fail + try { + conn.createStatement().execute("DROP TABLE " + fullTableName ); + fail(); + } + catch (SQLException e) { + assertEquals(SQLExceptionCode.CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode()); + } - validateCannotDropTableWithChildViewsWithoutCascade(conn, fullTableName); + // drop table cascade should succeed + conn.createStatement().execute("DROP TABLE " + fullTableName + " CASCADE"); - // Execute DROP...CASCADE + validateViewDoesNotExist(conn, fullViewName1); + validateViewDoesNotExist(conn, fullViewName2); + + } + + @Test + public void testRecreateDroppedTableWithChildViews() throws Exception { + Connection conn = DriverManager.getConnection(getUrl()); + String fullTableName = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); + String fullViewName1 = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); + String fullViewName2 = SchemaUtil.getTableName(SCHEMA3, generateUniqueName()); + + String tableDdl = "CREATE TABLE " + fullTableName + " (k INTEGER NOT NULL PRIMARY KEY, v1 DATE)" + tableDDLOptions; + conn.createStatement().execute(tableDdl); + String ddl = "CREATE VIEW " + fullViewName1 + " (v2 VARCHAR) AS SELECT * FROM " + fullTableName + " WHERE k > 5"; + conn.createStatement().execute(ddl); + String indexName = generateUniqueName(); + ddl = "CREATE INDEX " + indexName + " on " + fullViewName1 + "(v2)"; + conn.createStatement().execute(ddl); + ddl = "CREATE VIEW " + fullViewName2 + "(v2 VARCHAR) AS SELECT * FROM " + fullTableName + " WHERE k > 10"; + conn.createStatement().execute(ddl); + + // drop table cascade should succeed conn.createStatement().execute("DROP TABLE " + fullTableName + " CASCADE"); validateViewDoesNotExist(conn, fullViewName1); validateViewDoesNotExist(conn, fullViewName2); + + // recreate the table that was dropped + conn.createStatement().execute(tableDdl); + // the two child views should still not exist + try { + PhoenixRuntime.getTableNoCache(conn, fullViewName1); + fail(); + } catch (SQLException e) { + } + try { + PhoenixRuntime.getTableNoCache(conn, fullViewName2); + fail(); + } catch (SQLException e) { + } } @Test - public void testViewAndTableAndDropCascadeWithIndexes() throws Exception { + public void testRecreateIndexWhoseAncestorWasDropped() throws Exception { + Connection conn = DriverManager.getConnection(getUrl()); + String fullTableName1 = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); + String fullViewName1 = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); + String fullTableName2 = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); - // Setup - Tables and Views with Indexes - Connection conn = DriverManager.getConnection(getUrl()); - if (tableDDLOptions.length()!=0) - tableDDLOptions+=","; - tableDDLOptions+="IMMUTABLE_ROWS=true"; + String tableDdl = "CREATE TABLE " + fullTableName1 + " (k INTEGER NOT NULL PRIMARY KEY, v1 DATE)" + tableDDLOptions; + conn.createStatement().execute(tableDdl); + tableDdl = "CREATE TABLE " + fullTableName2 + " (k INTEGER NOT NULL PRIMARY KEY, v3 DATE)" + tableDDLOptions; + conn.createStatement().execute(tableDdl); + String ddl = "CREATE VIEW " + fullViewName1 + " (v2 VARCHAR) AS SELECT * FROM " + fullTableName1 + " WHERE k > 5"; + conn.createStatement().execute(ddl); + String indexName = generateUniqueName(); + ddl = "CREATE INDEX " + indexName + " on " + fullViewName1 + "(v2)"; + conn.createStatement().execute(ddl); + try { + // this should fail because an index with this name is present + ddl = "CREATE INDEX " + indexName + " on " + fullTableName2 + "(v1)"; + conn.createStatement().execute(ddl); + fail(); + } + catch(SQLException e) { + } + + // drop table cascade should succeed + conn.createStatement().execute("DROP TABLE " + fullTableName1 + " CASCADE"); + + // should be able to reuse the index name + ddl = "CREATE INDEX " + indexName + " on " + fullTableName2 + "(v3)"; + conn.createStatement().execute(ddl); + + String fullIndexName = SchemaUtil.getTableName(SCHEMA2, indexName); + PTable index = PhoenixRuntime.getTableNoCache(conn, fullIndexName); + // the index should have v3 but not v2 + validateCols(index); + } + + @Test + public void testRecreateViewWhoseParentWasDropped() throws Exception { + Connection conn = DriverManager.getConnection(getUrl()); + String fullTableName1 = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); + String fullViewName1 = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); + String fullTableName2 = SchemaUtil.getTableName(SCHEMA3, generateUniqueName()); + + String tableDdl = "CREATE TABLE " + fullTableName1 + " (k INTEGER NOT NULL PRIMARY KEY, v1 DATE)" + tableDDLOptions; + conn.createStatement().execute(tableDdl); + tableDdl = "CREATE TABLE " + fullTableName2 + " (k INTEGER NOT NULL PRIMARY KEY, v1 DATE)" + tableDDLOptions; + conn.createStatement().execute(tableDdl); + String ddl = "CREATE VIEW " + fullViewName1 + " (v2 VARCHAR) AS SELECT * FROM " + fullTableName1 + " WHERE k > 5"; + conn.createStatement().execute(ddl); + + // drop table cascade should succeed + conn.createStatement().execute("DROP TABLE " + fullTableName1 + " CASCADE"); + + // should be able to reuse the view name + ddl = "CREATE VIEW " + fullViewName1 + " (v3 VARCHAR) AS SELECT * FROM " + fullTableName2 + " WHERE k > 5"; + conn.createStatement().execute(ddl); + + PTable view = PhoenixRuntime.getTableNoCache(conn, fullViewName1); + // the view should have v3 but not v2 + validateCols(view); + } + + private void validateCols(PTable table) { + final String prefix = table.getType() == PTableType.INDEX ? "0:" : ""; + Predicate<PColumn> predicate = new Predicate<PColumn>() { + @Override + public boolean apply(PColumn col) { + return col.getName().getString().equals(prefix + "V3") + || col.getName().getString().equals(prefix + "V2"); + } + }; + List<PColumn> colList = table.getColumns(); + Collection<PColumn> filteredCols = Collections2.filter(colList, predicate); + assertEquals(1, filteredCols.size()); + assertEquals(prefix + "V3", filteredCols.iterator().next().getName().getString()); + } + + @Test + public void testViewAndTableAndDropCascadeWithIndexes() throws Exception { + // Setup - Tables and Views with Indexes + Connection conn = DriverManager.getConnection(getUrl()); + if (tableDDLOptions.length()!=0) + tableDDLOptions+=","; + tableDDLOptions+="IMMUTABLE_ROWS=true"; + String fullTableName = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); String ddl = "CREATE TABLE " + fullTableName + " (k INTEGER NOT NULL PRIMARY KEY, v1 DATE)" + tableDDLOptions; conn.createStatement().execute(ddl); - String viewSchemaName = "S_" + generateUniqueName(); - String fullViewName1 = SchemaUtil.getTableName(viewSchemaName, "V_" + generateUniqueName()); - String fullViewName2 = SchemaUtil.getTableName(viewSchemaName, "V_" + generateUniqueName()); + String fullViewName1 = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); + String fullViewName2 = SchemaUtil.getTableName(SCHEMA3, generateUniqueName()); String indexName1 = "I_" + generateUniqueName(); String indexName2 = "I_" + generateUniqueName(); String indexName3 = "I_" + generateUniqueName(); + ddl = "CREATE INDEX " + indexName1 + " ON " + fullTableName + " (v1)"; conn.createStatement().execute(ddl); ddl = "CREATE VIEW " + fullViewName1 + " (v2 VARCHAR) AS SELECT * FROM " + fullTableName + " WHERE k > 5"; @@ -466,9 +555,8 @@ public class ViewIT extends BaseViewIT { conn.createStatement().execute(ddl); ddl = "CREATE INDEX " + indexName3 + " ON " + fullViewName2 + " (v2)"; conn.createStatement().execute(ddl); - - validateCannotDropTableWithChildViewsWithoutCascade(conn, fullTableName); + // Execute DROP...CASCADE conn.createStatement().execute("DROP TABLE " + fullTableName + " CASCADE"); @@ -478,28 +566,16 @@ public class ViewIT extends BaseViewIT { } - private void validateCannotDropTableWithChildViewsWithoutCascade(Connection conn, String tableName) throws SQLException { - String ddl; - try { - ddl = "DROP TABLE " + tableName; - conn.createStatement().execute(ddl); - fail("Should not be able to drop table " + tableName + " with child views without explictly specifying CASCADE"); - } catch (SQLException e) { - assertEquals(SQLExceptionCode.CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode()); - } - } - - - private void validateViewDoesNotExist(Connection conn, String fullViewName) throws SQLException { - try { - String ddl1 = "DROP VIEW " + fullViewName; + private void validateViewDoesNotExist(Connection conn, String fullViewName) throws SQLException { + try { + String ddl1 = "DROP VIEW " + fullViewName; conn.createStatement().execute(ddl1); fail("View " + fullViewName + " should have been deleted when parent was dropped"); } catch (TableNotFoundException e) { - //Expected + //Expected } - } - + } + @Test public void testViewUsesTableGlobalIndex() throws Exception { testViewUsesTableIndex(false); @@ -515,17 +591,17 @@ public class ViewIT extends BaseViewIT { ResultSet rs; // Use unique name for table with local index as otherwise we run into issues // when we attempt to drop the table (with the drop metadata option set to false - String fullTableName = this.fullTableName + (localIndex ? "_WITH_LI" : "_WITHOUT_LI"); + String fullTableName = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()) + (localIndex ? "_WITH_LI" : "_WITHOUT_LI"); Connection conn = DriverManager.getConnection(getUrl()); String ddl = "CREATE TABLE " + fullTableName + " (k1 INTEGER NOT NULL, k2 INTEGER NOT NULL, k3 DECIMAL, s1 VARCHAR, s2 VARCHAR CONSTRAINT pk PRIMARY KEY (k1, k2, k3))" + tableDDLOptions; conn.createStatement().execute(ddl); String indexName1 = "I_" + generateUniqueName(); - String fullIndexName1 = SchemaUtil.getTableName(schemaName, indexName1); + String fullIndexName1 = SchemaUtil.getTableName(SCHEMA1, indexName1); conn.createStatement().execute("CREATE " + (localIndex ? "LOCAL " : "") + " INDEX " + indexName1 + " ON " + fullTableName + "(k3, k2) INCLUDE(s1, s2)"); String indexName2 = "I_" + generateUniqueName(); conn.createStatement().execute("CREATE INDEX " + indexName2 + " ON " + fullTableName + "(k3, k2, s2)"); - String fullViewName = "V_" + generateUniqueName(); + String fullViewName = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); ddl = "CREATE VIEW " + fullViewName + " AS SELECT * FROM " + fullTableName + " WHERE s1 = 'foo'"; conn.createStatement().execute(ddl); String[] s1Values = {"foo","bar"}; @@ -564,15 +640,20 @@ public class ViewIT extends BaseViewIT { @Test public void testCreateViewDefinesPKColumn() throws Exception { Connection conn = DriverManager.getConnection(getUrl()); + String fullTableName = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); + String fullViewName = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); + String ddl = "CREATE TABLE " + fullTableName + " (k1 INTEGER NOT NULL, k2 INTEGER NOT NULL, v1 DECIMAL, CONSTRAINT pk PRIMARY KEY (k1, k2))" + tableDDLOptions; conn.createStatement().execute(ddl); - String fullViewName = "V_" + generateUniqueName(); ddl = "CREATE VIEW " + fullViewName + "(v2 VARCHAR, k3 VARCHAR PRIMARY KEY) AS SELECT * FROM " + fullTableName + " WHERE K1 = 1"; conn.createStatement().execute(ddl); // assert PK metadata - ResultSet rs = conn.getMetaData().getPrimaryKeys(null, null, fullViewName); - assertPKs(rs, new String[] {"K1", "K2", "K3"}); + ResultSet rs = + conn.getMetaData().getPrimaryKeys(null, + SchemaUtil.getSchemaNameFromFullName(fullViewName), + SchemaUtil.getTableNameFromFullName(fullViewName)); + assertPKs(rs, new String[] {"K3"}); // sanity check upserts into base table and view conn.createStatement().executeUpdate("upsert into " + fullTableName + " (k1, k2, v1) values (1, 1, 1)"); @@ -593,43 +674,54 @@ public class ViewIT extends BaseViewIT { @Test public void testCreateViewDefinesPKConstraint() throws Exception { Connection conn = DriverManager.getConnection(getUrl()); + String fullTableName = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); + String fullViewName = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); + String ddl = "CREATE TABLE " + fullTableName + " (k1 INTEGER NOT NULL, k2 INTEGER NOT NULL, v1 DECIMAL, CONSTRAINT pk PRIMARY KEY (k1, k2))" + tableDDLOptions; conn.createStatement().execute(ddl); - String fullViewName = "V_" + generateUniqueName(); ddl = "CREATE VIEW " + fullViewName + "(v2 VARCHAR, k3 VARCHAR, k4 INTEGER NOT NULL, CONSTRAINT PKVEW PRIMARY KEY (k3, k4)) AS SELECT * FROM " + fullTableName + " WHERE K1 = 1"; conn.createStatement().execute(ddl); - + // assert PK metadata - ResultSet rs = conn.getMetaData().getPrimaryKeys(null, null, fullViewName); - assertPKs(rs, new String[] {"K1", "K2", "K3", "K4"}); + ResultSet rs = + conn.getMetaData().getPrimaryKeys(null, + SchemaUtil.getSchemaNameFromFullName(fullViewName), + SchemaUtil.getTableNameFromFullName(fullViewName)); + assertPKs(rs, new String[] {"K3", "K4"}); } @Test public void testViewAddsPKColumn() throws Exception { Connection conn = DriverManager.getConnection(getUrl()); - String fullTableName2 = fullTableName; - String ddl = "CREATE TABLE " + fullTableName2 + " (k1 INTEGER NOT NULL, k2 INTEGER NOT NULL, v1 DECIMAL, CONSTRAINT pk PRIMARY KEY (k1, k2))" + tableDDLOptions; + String fullTableName = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); + String viewName = generateUniqueName(); + String fullViewName = SchemaUtil.getTableName(SCHEMA2, viewName); + + String ddl = "CREATE TABLE " + fullTableName + " (k1 INTEGER NOT NULL, k2 INTEGER NOT NULL, v1 DECIMAL, CONSTRAINT pk PRIMARY KEY (k1, k2))" + tableDDLOptions; conn.createStatement().execute(ddl); - String fullViewName = "V_" + generateUniqueName(); ddl = "CREATE VIEW " + fullViewName + " AS SELECT * FROM " + fullTableName + " WHERE v1 = 1.0"; conn.createStatement().execute(ddl); + ddl = "ALTER VIEW " + fullViewName + " ADD k3 VARCHAR PRIMARY KEY, k4 VARCHAR PRIMARY KEY, v2 INTEGER"; conn.createStatement().execute(ddl); // assert PK metadata - ResultSet rs = conn.getMetaData().getPrimaryKeys(null, null, fullViewName); - assertPKs(rs, new String[] {"K1", "K2", "K3", "K4"}); + ResultSet rs = conn.getMetaData().getPrimaryKeys(null, SCHEMA2, viewName); + assertPKs(rs, new String[] {"K3", "K4"}); } @Test public void testViewAddsPKColumnWhoseParentsLastPKIsVarLength() throws Exception { Connection conn = DriverManager.getConnection(getUrl()); + String fullTableName = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); + String fullViewName = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); + String ddl = "CREATE TABLE " + fullTableName + " (k1 INTEGER NOT NULL, k2 VARCHAR NOT NULL, v1 DECIMAL, CONSTRAINT pk PRIMARY KEY (k1, k2))" + tableDDLOptions; conn.createStatement().execute(ddl); - String fullViewName1 = "V_" + generateUniqueName(); - ddl = "CREATE VIEW " + fullViewName1 + " AS SELECT * FROM " + fullTableName + " WHERE v1 = 1.0"; + ddl = "CREATE VIEW " + fullViewName + " AS SELECT * FROM " + fullTableName + " WHERE v1 = 1.0"; conn.createStatement().execute(ddl); - ddl = "ALTER VIEW " + fullViewName1 + " ADD k3 VARCHAR PRIMARY KEY, k4 VARCHAR PRIMARY KEY, v2 INTEGER"; + + ddl = "ALTER VIEW " + fullViewName + " ADD k3 VARCHAR PRIMARY KEY, k4 VARCHAR PRIMARY KEY, v2 INTEGER"; try { conn.createStatement().execute(ddl); fail("View cannot extend PK if parent's last PK is variable length. See https://issues.apache.org/jira/browse/PHOENIX-978."); @@ -639,7 +731,7 @@ public class ViewIT extends BaseViewIT { String fullViewName2 = "V_" + generateUniqueName(); ddl = "CREATE VIEW " + fullViewName2 + " (k3 VARCHAR PRIMARY KEY) AS SELECT * FROM " + fullTableName + " WHERE v1 = 1.0"; try { - conn.createStatement().execute(ddl); + conn.createStatement().execute(ddl); } catch (SQLException e) { assertEquals(CANNOT_MODIFY_VIEW_PK.getErrorCode(), e.getErrorCode()); } @@ -648,23 +740,28 @@ public class ViewIT extends BaseViewIT { @Test(expected=ColumnAlreadyExistsException.class) public void testViewAddsClashingPKColumn() throws Exception { Connection conn = DriverManager.getConnection(getUrl()); + String fullTableName = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); + String fullViewName = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); + String ddl = "CREATE TABLE " + fullTableName + " (k1 INTEGER NOT NULL, k2 INTEGER NOT NULL, v1 DECIMAL, CONSTRAINT pk PRIMARY KEY (k1, k2))" + tableDDLOptions; conn.createStatement().execute(ddl); - String fullViewName = "V_" + generateUniqueName(); ddl = "CREATE VIEW " + fullViewName + " AS SELECT * FROM " + fullTableName + " WHERE v1 = 1.0"; conn.createStatement().execute(ddl); + ddl = "ALTER VIEW " + fullViewName + " ADD k3 VARCHAR PRIMARY KEY, k2 VARCHAR PRIMARY KEY, v2 INTEGER"; conn.createStatement().execute(ddl); } - + @Test public void testViewAddsNotNullPKColumn() throws Exception { Connection conn = DriverManager.getConnection(getUrl()); + String fullTableName = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); + String fullViewName = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); String ddl = "CREATE TABLE " + fullTableName + " (k1 INTEGER NOT NULL, k2 INTEGER NOT NULL, v1 DECIMAL, CONSTRAINT pk PRIMARY KEY (k1, k2))" + tableDDLOptions; conn.createStatement().execute(ddl); - String fullViewName = "V_" + generateUniqueName(); ddl = "CREATE VIEW " + fullViewName + " AS SELECT * FROM " + fullTableName + " WHERE v1 = 1.0"; conn.createStatement().execute(ddl); + try { ddl = "ALTER VIEW " + fullViewName + " ADD k3 VARCHAR NOT NULL PRIMARY KEY"; conn.createStatement().execute(ddl); @@ -677,15 +774,17 @@ public class ViewIT extends BaseViewIT { @Test public void testQueryViewStatementOptimization() throws Exception { Connection conn = DriverManager.getConnection(getUrl()); + String fullTableName = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); + String fullViewName1 = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); + String fullViewName2 = SchemaUtil.getTableName(SCHEMA3, generateUniqueName()); String sql = "CREATE TABLE " + fullTableName + " (k1 INTEGER NOT NULL, k2 INTEGER NOT NULL, v1 DECIMAL, CONSTRAINT pk PRIMARY KEY (k1, k2))" + tableDDLOptions; conn.createStatement().execute(sql); - String fullViewName1 = "V_" + generateUniqueName(); sql = "CREATE VIEW " + fullViewName1 + " AS SELECT * FROM " + fullTableName; conn.createStatement().execute(sql); - String fullViewName2 = "V_" + generateUniqueName(); sql = "CREATE VIEW " + fullViewName2 + " AS SELECT * FROM " + fullTableName + " WHERE k1 = 1.0"; conn.createStatement().execute(sql); + sql = "SELECT * FROM " + fullViewName1 + " order by k1, k2"; PreparedStatement stmt = conn.prepareStatement(sql); QueryPlan plan = PhoenixRuntime.getOptimizedQueryPlan(stmt); @@ -702,13 +801,14 @@ public class ViewIT extends BaseViewIT { Properties props = new Properties(); Connection conn1 = DriverManager.getConnection(getUrl(), props); conn1.setAutoCommit(true); - String tableName=generateUniqueName(); - String viewName=generateUniqueName(); + String tableName = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); + String viewName = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); conn1.createStatement().execute( "CREATE TABLE "+tableName+" (k VARCHAR PRIMARY KEY, v1 VARCHAR, v2 VARCHAR) UPDATE_CACHE_FREQUENCY=1000000"); conn1.createStatement().execute("upsert into "+tableName+" values ('row1', 'value1', 'key1')"); conn1.createStatement().execute( "CREATE VIEW "+viewName+" (v43 VARCHAR) AS SELECT * FROM "+tableName+" WHERE v1 = 'value1'"); + ResultSet rs = conn1.createStatement() .executeQuery("SELECT * FROM "+tableName+" WHERE v1 = 'value1'"); assertTrue(rs.next()); @@ -724,60 +824,59 @@ public class ViewIT extends BaseViewIT { props.setProperty(QueryServices.IS_NAMESPACE_MAPPING_ENABLED, Boolean.TRUE.toString()); try (Connection conn = DriverManager.getConnection(getUrl(), props); - HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HBaseAdmin admin = + conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { conn.createStatement().execute("CREATE SCHEMA " + NS); // test for a view that is in non-default schema - { - HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(NS, TBL)); - desc.addFamily(new HColumnDescriptor(CF)); - admin.createTable(desc); + HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(NS, TBL)); + desc.addFamily(new HColumnDescriptor(CF)); + admin.createTable(desc); - String view = NS + "." + TBL; - conn.createStatement().execute( - "CREATE VIEW " + view + " (PK VARCHAR PRIMARY KEY, " + CF + ".COL VARCHAR)"); + String view1 = NS + "." + TBL; + conn.createStatement().execute( + "CREATE VIEW " + view1 + " (PK VARCHAR PRIMARY KEY, " + CF + ".COL VARCHAR)"); - assertTrue(QueryUtil.getExplainPlan( - conn.createStatement().executeQuery("explain select * from " + view)) + assertTrue(QueryUtil + .getExplainPlan( + conn.createStatement().executeQuery("explain select * from " + view1)) .contains(NS + ":" + TBL)); - conn.createStatement().execute("DROP VIEW " + view); - } + - // test for a view whose name contains a dot (e.g. "AAA.BBB") in default schema (for backward compatibility) - { - HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(NS + "." + TBL)); - desc.addFamily(new HColumnDescriptor(CF)); - admin.createTable(desc); + // test for a view whose name contains a dot (e.g. "AAA.BBB") in default schema (for + // backward compatibility) + desc = new HTableDescriptor(TableName.valueOf(NS + "." + TBL)); + desc.addFamily(new HColumnDescriptor(CF)); + admin.createTable(desc); - String view = "\"" + NS + "." + TBL + "\""; - conn.createStatement().execute( - "CREATE VIEW " + view + " (PK VARCHAR PRIMARY KEY, " + CF + ".COL VARCHAR)"); + String view2 = "\"" + NS + "." + TBL + "\""; + conn.createStatement().execute( + "CREATE VIEW " + view2 + " (PK VARCHAR PRIMARY KEY, " + CF + ".COL VARCHAR)"); - assertTrue(QueryUtil.getExplainPlan( - conn.createStatement().executeQuery("explain select * from " + view)) + assertTrue(QueryUtil + .getExplainPlan( + conn.createStatement().executeQuery("explain select * from " + view2)) .contains(NS + "." + TBL)); - conn.createStatement().execute("DROP VIEW " + view); - } - // test for a view whose name contains a dot (e.g. "AAA.BBB") in non-default schema - { - HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(NS, NS + "." + TBL)); - desc.addFamily(new HColumnDescriptor(CF)); - admin.createTable(desc); + desc = new HTableDescriptor(TableName.valueOf(NS, NS + "." + TBL)); + desc.addFamily(new HColumnDescriptor(CF)); + admin.createTable(desc); - String view = NS + ".\"" + NS + "." + TBL + "\""; - conn.createStatement().execute( - "CREATE VIEW " + view + " (PK VARCHAR PRIMARY KEY, " + CF + ".COL VARCHAR)"); + String view3 = NS + ".\"" + NS + "." + TBL + "\""; + conn.createStatement().execute( + "CREATE VIEW " + view3 + " (PK VARCHAR PRIMARY KEY, " + CF + ".COL VARCHAR)"); - assertTrue(QueryUtil.getExplainPlan( - conn.createStatement().executeQuery("explain select * from " + view)) + assertTrue(QueryUtil + .getExplainPlan( + conn.createStatement().executeQuery("explain select * from " + view3)) .contains(NS + ":" + NS + "." + TBL)); - - conn.createStatement().execute("DROP VIEW " + view); - } + + conn.createStatement().execute("DROP VIEW " + view1); + conn.createStatement().execute("DROP VIEW " + view2); + conn.createStatement().execute("DROP VIEW " + view3); conn.createStatement().execute("DROP SCHEMA " + NS); } @@ -793,14 +892,14 @@ public class ViewIT extends BaseViewIT { } @Test - public void testCompositeDescPK() throws SQLException { + public void testCompositeDescPK() throws Exception { Properties props = new Properties(); try (Connection globalConn = DriverManager.getConnection(getUrl(), props)) { - String tableName = generateUniqueName(); - String viewName1 = generateUniqueName(); - String viewName2 = generateUniqueName(); - String viewName3 = generateUniqueName(); - String viewName4 = generateUniqueName(); + String tableName = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); + String viewName1 = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); + String viewName2 = SchemaUtil.getTableName(SCHEMA3, generateUniqueName()); + String viewName3 = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); + String viewName4 = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); // create global base table globalConn.createStatement().execute("CREATE TABLE " + tableName @@ -823,6 +922,17 @@ public class ViewIT extends BaseViewIT { + " (pk1 VARCHAR(10) NOT NULL, pk2 VARCHAR(10) NOT NULL, col1 DATE, col3 DECIMAL CONSTRAINT PK PRIMARY KEY (pk1 DESC, pk2 DESC)) AS SELECT * FROM " + tableName + " WHERE KEY_PREFIX = 'abc' "); + // view with composite PK with multiple Date PK values DESC + tenantConn.createStatement() + .execute("CREATE VIEW " + viewName3 + + " (pk1 DATE(10) NOT NULL, pk2 DATE(10) NOT NULL, col1 VARCHAR(10), col3 DECIMAL CONSTRAINT PK PRIMARY KEY (pk1 DESC, pk2 DESC)) AS SELECT * FROM " + + tableName + " WHERE KEY_PREFIX = 'ab3' "); + + tenantConn.createStatement() + .execute("CREATE VIEW " + viewName4 + + " (pk1 DATE(10) NOT NULL, pk2 DECIMAL NOT NULL, pk3 VARCHAR(10) NOT NULL, col3 DECIMAL CONSTRAINT PK PRIMARY KEY (pk1 DESC, pk2 DESC, pk3 DESC)) AS SELECT * FROM " + + tableName + " WHERE KEY_PREFIX = 'ab4' "); + // upsert rows upsertRows(viewName1, tenantConn); upsertRows(viewName2, tenantConn); @@ -835,12 +945,6 @@ public class ViewIT extends BaseViewIT { validate(viewName1, tenantConn, whereClauses, expectedArray); validate(viewName2, tenantConn, whereClauses, expectedArray); - // view with composite PK with multiple Date PK values DESC - tenantConn.createStatement() - .execute("CREATE VIEW " + viewName3 - + " (pk1 DATE(10) NOT NULL, pk2 DATE(10) NOT NULL, col1 VARCHAR(10), col3 DECIMAL CONSTRAINT PK PRIMARY KEY (pk1 DESC, pk2 DESC)) AS SELECT * FROM " - + tableName + " WHERE KEY_PREFIX = 'ab3' "); - tenantConn.createStatement().execute("UPSERT INTO " + viewName3 + " (pk1, pk2, col1, col3) VALUES (TO_DATE('2017-10-16 22:00:00', 'yyyy-MM-dd HH:mm:ss'), TO_DATE('2017-10-16 21:00:00', 'yyyy-MM-dd HH:mm:ss'), 'txt1', 10)"); tenantConn.createStatement().execute("UPSERT INTO " + viewName3 @@ -862,11 +966,6 @@ public class ViewIT extends BaseViewIT { "pk1 < TO_DATE('2017-10-16 22:00:00', 'yyyy-MM-dd HH:mm:ss')" }; validate(viewName3, tenantConn, view3WhereClauses, expectedArray); - tenantConn.createStatement() - .execute("CREATE VIEW " + viewName4 - + " (pk1 DATE(10) NOT NULL, pk2 DECIMAL NOT NULL, pk3 VARCHAR(10) NOT NULL, col3 DECIMAL CONSTRAINT PK PRIMARY KEY (pk1 DESC, pk2 DESC, pk3 DESC)) AS SELECT * FROM " - + tableName + " WHERE KEY_PREFIX = 'ab4' "); - tenantConn.createStatement().execute("UPSERT INTO " + viewName4 + " (pk1, pk2, pk3, col3) VALUES (TO_DATE('2017-10-16 22:00:00', 'yyyy-MM-dd HH:mm:ss'), 1, 'txt1', 10)"); tenantConn.createStatement().execute("UPSERT INTO " + viewName4 @@ -901,8 +1000,8 @@ public class ViewIT extends BaseViewIT { Connection conn2 = DriverManager.getConnection(getUrl()); Statement s = conn.createStatement(); Statement s2 = conn2.createStatement()) { - String tableName = generateUniqueName(); - String viewName = generateUniqueName(); + String tableName = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); + String viewName = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); String indexName = generateUniqueName(); helpTestQueryForViewOnTableThatHasIndex(s, s2, tableName, viewName, indexName); } @@ -912,8 +1011,8 @@ public class ViewIT extends BaseViewIT { public void testQueryForViewOnTableThatHasIndex() throws SQLException { try (Connection conn = DriverManager.getConnection(getUrl()); Statement s = conn.createStatement()) { - String tableName = generateUniqueName(); - String viewName = generateUniqueName(); + String tableName = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); + String viewName = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); String indexName = generateUniqueName(); helpTestQueryForViewOnTableThatHasIndex(s, s, tableName, viewName, indexName); } @@ -966,4 +1065,237 @@ public class ViewIT extends BaseViewIT { + " (pk1, pk2, col1, col3) VALUES ('testb', 'testa', TO_DATE('2017-10-16 22:00:00', 'yyyy-MM-dd HH:mm:ss'), 10)"); tenantConn.commit(); } + + @Test + public void testUpdatingPropertyOnBaseTable() throws Exception { + String fullTableName = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); + String fullViewName = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); + try (Connection conn = DriverManager.getConnection(getUrl())) { + conn.createStatement() + .execute("create table " + fullTableName + + "(tenantId CHAR(15) NOT NULL, pk1 integer NOT NULL, v varchar CONSTRAINT PK PRIMARY KEY " + + "(tenantId, pk1)) MULTI_TENANT=true"); + conn.createStatement().execute("CREATE VIEW " + fullViewName + " AS SELECT * FROM " + fullTableName); + + conn.createStatement() + .execute("ALTER TABLE " + fullTableName + " set IMMUTABLE_ROWS = true"); + + // fetch the latest tables + PTable table = PhoenixRuntime.getTableNoCache(conn, fullTableName); + PTable view = PhoenixRuntime.getTableNoCache(conn, fullViewName); + assertEquals("IMMUTABLE_ROWS property set incorrectly", true, table.isImmutableRows()); + assertEquals("IMMUTABLE_ROWS property set incorrectly", true, view.isImmutableRows()); + } + } + + public static String testUpdatableView(String fullTableName, String fullViewName, String fullChildViewName, + String childViewDDL, Integer saltBuckets, String tableDDLOptions) throws Exception { + Connection conn = DriverManager.getConnection(getUrl()); + if (saltBuckets != null) { + if (tableDDLOptions.length() != 0) + tableDDLOptions += ","; + tableDDLOptions += (" SALT_BUCKETS=" + saltBuckets); + } + String ddl = "CREATE TABLE " + fullTableName + + " (k1 INTEGER NOT NULL, k2 INTEGER NOT NULL, k3 DECIMAL, s VARCHAR CONSTRAINT pk PRIMARY KEY (k1, k2, k3))" + + tableDDLOptions; + conn.createStatement().execute(ddl); + ddl = "CREATE VIEW " + fullViewName + " AS SELECT * FROM " + fullTableName + " WHERE k1 = 1"; + conn.createStatement().execute(ddl); + ArrayList<String> splitPoints = Lists.newArrayList(fullTableName, fullViewName); + if (fullChildViewName != null) { + conn.createStatement().execute(childViewDDL); + splitPoints.add(fullChildViewName); + } + + for (int i = 0; i < 10; i++) { + conn.createStatement().execute("UPSERT INTO " + fullTableName + " VALUES(" + (i % 4) + "," + (i + 100) + "," + + (i > 5 ? 2 : 1) + ")"); + } + conn.commit(); + ResultSet rs; + + rs = conn.createStatement().executeQuery("SELECT count(*) FROM " + fullTableName); + assertTrue(rs.next()); + assertEquals(10, rs.getInt(1)); + rs = conn.createStatement().executeQuery("SELECT count(*) FROM " + fullViewName); + assertTrue(rs.next()); + assertEquals(3, rs.getInt(1)); + rs = conn.createStatement().executeQuery("SELECT k1, k2, k3 FROM " + fullViewName); + assertTrue(rs.next()); + assertEquals(1, rs.getInt(1)); + assertEquals(101, rs.getInt(2)); + assertEquals(1, rs.getInt(3)); + assertTrue(rs.next()); + assertEquals(1, rs.getInt(1)); + assertEquals(105, rs.getInt(2)); + assertEquals(1, rs.getInt(3)); + assertTrue(rs.next()); + assertEquals(1, rs.getInt(1)); + assertEquals(109, rs.getInt(2)); + assertEquals(2, rs.getInt(3)); + assertFalse(rs.next()); + + conn.createStatement().execute("UPSERT INTO " + fullViewName + "(k2,S,k3) VALUES(120,'foo',50.0)"); + conn.createStatement().execute("UPSERT INTO " + fullViewName + "(k2,S,k3) VALUES(121,'bar',51.0)"); + conn.commit(); + rs = conn.createStatement().executeQuery("SELECT k1, k2 FROM " + fullViewName + " WHERE k2 >= 120"); + assertTrue(rs.next()); + assertEquals(1, rs.getInt(1)); + assertEquals(120, rs.getInt(2)); + assertTrue(rs.next()); + assertEquals(1, rs.getInt(1)); + assertEquals(121, rs.getInt(2)); + assertFalse(rs.next()); + conn.close(); + return fullViewName; + } + + public static Pair<String, Scan> testUpdatableViewIndex(String fullTableName, Integer saltBuckets, + boolean localIndex, String viewName) throws Exception { + ResultSet rs; + Connection conn = DriverManager.getConnection(getUrl()); + String viewIndexName1 = "I_" + generateUniqueName(); + String viewIndexPhysicalName = MetaDataUtil.getViewIndexPhysicalName(fullTableName); + if (localIndex) { + conn.createStatement().execute("CREATE LOCAL INDEX " + viewIndexName1 + " on " + viewName + "(k3)"); + } else { + conn.createStatement().execute("CREATE INDEX " + viewIndexName1 + " on " + viewName + "(k3) include (s)"); + } + conn.createStatement().execute("UPSERT INTO " + viewName + "(k2,S,k3) VALUES(120,'foo',50.0)"); + conn.commit(); + + analyzeTable(conn, viewName); + List<KeyRange> splits = getAllSplits(conn, viewIndexName1); + // More guideposts with salted, since it's already pre-split at salt + // buckets + assertEquals(saltBuckets == null ? 6 : 8, splits.size()); + + String query = "SELECT k1, k2, k3, s FROM " + viewName + " WHERE k3 = 51.0"; + rs = conn.createStatement().executeQuery(query); + assertTrue(rs.next()); + assertEquals(1, rs.getInt(1)); + assertEquals(121, rs.getInt(2)); + assertTrue(BigDecimal.valueOf(51.0).compareTo(rs.getBigDecimal(3)) == 0); + assertEquals("bar", rs.getString(4)); + assertFalse(rs.next()); + rs = conn.createStatement().executeQuery("EXPLAIN " + query); + String queryPlan = QueryUtil.getExplainPlan(rs); + if (localIndex) { + assertEquals("CLIENT PARALLEL " + (saltBuckets == null ? 1 : saltBuckets) + "-WAY RANGE SCAN OVER " + + fullTableName + " [1,51]\n" + " SERVER FILTER BY FIRST KEY ONLY\n" + "CLIENT MERGE SORT", + queryPlan); + } else { + assertEquals(saltBuckets == null + ? "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + viewIndexPhysicalName + " [" + Short.MIN_VALUE + ",51]" + : "CLIENT PARALLEL " + saltBuckets + "-WAY RANGE SCAN OVER " + viewIndexPhysicalName + " [0," + + Short.MIN_VALUE + ",51] - [" + (saltBuckets.intValue() - 1) + "," + Short.MIN_VALUE + + ",51]\nCLIENT MERGE SORT", + queryPlan); + } + + String viewIndexName2 = "I_" + generateUniqueName(); + if (localIndex) { + conn.createStatement().execute("CREATE LOCAL INDEX " + viewIndexName2 + " on " + viewName + "(s)"); + } else { + conn.createStatement().execute("CREATE INDEX " + viewIndexName2 + " on " + viewName + "(s)"); + } + + // new index hasn't been analyzed yet + splits = getAllSplits(conn, viewIndexName2); + assertEquals(saltBuckets == null ? 1 : 3, splits.size()); + + // analyze table should analyze all view data + analyzeTable(conn, fullTableName); + splits = getAllSplits(conn, viewIndexName2); + assertEquals(saltBuckets == null ? 6 : 8, splits.size()); + + query = "SELECT k1, k2, s FROM " + viewName + " WHERE s = 'foo'"; + Statement statement = conn.createStatement(); + rs = statement.executeQuery(query); + Scan scan = statement.unwrap(PhoenixStatement.class).getQueryPlan().getContext().getScan(); + assertTrue(rs.next()); + assertEquals(1, rs.getInt(1)); + assertEquals(120, rs.getInt(2)); + assertEquals("foo", rs.getString(3)); + assertFalse(rs.next()); + rs = conn.createStatement().executeQuery("EXPLAIN " + query); + String physicalTableName; + if (localIndex) { + physicalTableName = fullTableName; + assertEquals("CLIENT PARALLEL " + (saltBuckets == null ? 1 : saltBuckets) + "-WAY RANGE SCAN OVER " + + fullTableName + " [" + (2) + ",'foo']\n" + " SERVER FILTER BY FIRST KEY ONLY\n" + + "CLIENT MERGE SORT", QueryUtil.getExplainPlan(rs)); + } else { + physicalTableName = viewIndexPhysicalName; + assertEquals( + saltBuckets == null + ? "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + viewIndexPhysicalName + " [" + + (Short.MIN_VALUE + 1) + ",'foo']\n" + " SERVER FILTER BY FIRST KEY ONLY" + : "CLIENT PARALLEL " + saltBuckets + "-WAY RANGE SCAN OVER " + viewIndexPhysicalName + + " [0," + (Short.MIN_VALUE + 1) + ",'foo'] - [" + (saltBuckets.intValue() - 1) + + "," + (Short.MIN_VALUE + 1) + ",'foo']\n" + + " SERVER FILTER BY FIRST KEY ONLY\n" + "CLIENT MERGE SORT", + QueryUtil.getExplainPlan(rs)); + } + conn.close(); + return new Pair<>(physicalTableName, scan); + } + + @Test + public void testChildViewCreationFails() throws Exception { + Connection conn = DriverManager.getConnection(getUrl()); + String fullTableName = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); + String fullViewName1 = SchemaUtil.getTableName(SCHEMA2, FAILED_VIEWNAME); + String fullViewName2 = SchemaUtil.getTableName(SCHEMA3, generateUniqueName()); + + String tableDdl = "CREATE TABLE " + fullTableName + " (k INTEGER NOT NULL PRIMARY KEY, v1 DATE)" + tableDDLOptions; + conn.createStatement().execute(tableDdl); + String ddl = "CREATE VIEW " + fullViewName1 + " (v2 VARCHAR) AS SELECT * FROM " + fullTableName + " WHERE k > 5"; + try { + conn.createStatement().execute(ddl); + fail(); + } + catch (PhoenixIOException e){ + } + ddl = "CREATE VIEW " + fullViewName2 + "(v2 VARCHAR) AS SELECT * FROM " + fullTableName + " WHERE k > 10"; + conn.createStatement().execute(ddl); + + // the first child view should not exist + try { + PhoenixRuntime.getTableNoCache(conn, fullViewName1); + fail(); + } catch (SQLException e) { + } + + // we should be able to load the table + PhoenixRuntime.getTableNoCache(conn, fullTableName); + // we should be able to load the second view + PhoenixRuntime.getTableNoCache(conn, fullViewName2); + } + + private static final String FAILED_VIEWNAME = "FAILED_VIEW"; + private static final byte[] ROWKEY_TO_FAIL_BYTES = SchemaUtil.getTableKey(null, Bytes.toBytes(SCHEMA2), + Bytes.toBytes(FAILED_VIEWNAME)); + + public static class FailingRegionObserver extends SimpleRegionObserver { + @Override + public void preBatchMutate(ObserverContext<RegionCoprocessorEnvironment> c, + MiniBatchOperationInProgress<Mutation> miniBatchOp) throws IOException { + if (shouldFail(c, miniBatchOp.getOperation(0))) { + // throwing anything other than instances of IOException result + // in this coprocessor being unloaded + // DoNotRetryIOException tells HBase not to retry this mutation + // multiple times + throw new DoNotRetryIOException(); + } + } + + private boolean shouldFail(ObserverContext<RegionCoprocessorEnvironment> c, Mutation m) { + TableName tableName = c.getEnvironment().getRegion().getRegionInfo().getTable(); + return tableName.equals(PhoenixDatabaseMetaData.SYSTEM_CATALOG_HBASE_TABLE_NAME) + && (Bytes.equals(ROWKEY_TO_FAIL_BYTES, m.getRow())); + } + + } }
http://git-wip-us.apache.org/repos/asf/phoenix/blob/4d6dbf9c/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/BaseIndexIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/BaseIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/BaseIndexIT.java index f914256..d86037c 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/BaseIndexIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/BaseIndexIT.java @@ -48,6 +48,7 @@ import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.client.HBaseAdmin; +import org.apache.hadoop.hbase.client.HTable; import org.apache.hadoop.hbase.client.HTableInterface; import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.ResultScanner; @@ -124,6 +125,7 @@ public abstract class BaseIndexIT extends ParallelStatsDisabledIT { String tableName = "TBL_" + generateUniqueName(); String indexName = "IND_" + generateUniqueName(); String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName); + String fullIndexName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName); try (Connection conn = DriverManager.getConnection(getUrl(), props)) { conn.setAutoCommit(false); @@ -140,12 +142,12 @@ public abstract class BaseIndexIT extends ParallelStatsDisabledIT { ResultSet rs = conn.createStatement().executeQuery("EXPLAIN " + query); if(localIndex) { assertEquals( - "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + tableName + " [1]\n" + + "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + fullTableName + " [1]\n" + " SERVER FILTER BY FIRST KEY ONLY\n" + "CLIENT MERGE SORT", QueryUtil.getExplainPlan(rs)); } else { - assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER " + indexName + "\n" + assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER " + fullIndexName + "\n" + " SERVER FILTER BY FIRST KEY ONLY", QueryUtil.getExplainPlan(rs)); } @@ -168,7 +170,7 @@ public abstract class BaseIndexIT extends ParallelStatsDisabledIT { rs = conn.createStatement().executeQuery(query); assertTrue(rs.next()); - query = "SELECT char_col1, int_col1 from "+indexName; + query = "SELECT char_col1, int_col1 from "+fullIndexName; try{ rs = conn.createStatement().executeQuery(query); fail(); @@ -500,7 +502,7 @@ public abstract class BaseIndexIT extends ParallelStatsDisabledIT { Statement stmt = conn.createStatement(); stmt.execute(ddl); - query = "SELECT * FROM " + tableName; + query = "SELECT * FROM " + fullTableName; rs = conn.createStatement().executeQuery(query); assertFalse(rs.next()); @@ -772,10 +774,25 @@ public abstract class BaseIndexIT extends ParallelStatsDisabledIT { conn.createStatement().execute(ddl); stmt = conn.prepareStatement("UPSERT INTO " + fullTableName + "(k, v1) VALUES(?,?)"); - stmt.setString(1, "a"); - stmt.setString(2, "y"); + if (mutable) { + stmt.setString(1, "a"); + stmt.setString(2, "y"); + stmt.execute(); + conn.commit(); + } + stmt.setString(1, "b"); + stmt.setString(2, "x"); stmt.execute(); conn.commit(); + + // the index table is one row + HTable table = new HTable(getUtility().getConfiguration(), fullTableName); + ResultScanner resultScanner = table.getScanner(new Scan()); + for (Result result : resultScanner) { + System.out.println(result); + } + resultScanner.close(); + table.close(); query = "SELECT * FROM " + fullTableName; @@ -783,10 +800,15 @@ public abstract class BaseIndexIT extends ParallelStatsDisabledIT { rs = conn.createStatement().executeQuery(query); assertTrue(rs.next()); assertEquals("a", rs.getString(1)); - assertEquals("y", rs.getString(2)); + assertEquals(mutable ? "y" : "x", rs.getString(2)); + assertEquals("1", rs.getString(3)); + assertTrue(rs.next()); + assertEquals("b", rs.getString(1)); + assertEquals("x", rs.getString(2)); + assertNull(rs.getString(3)); assertFalse(rs.next()); + } } - } @Test public void testMultipleUpdatesAcrossRegions() throws Exception { @@ -1069,6 +1091,7 @@ public abstract class BaseIndexIT extends ParallelStatsDisabledIT { String tableName = "TBL_" + generateUniqueName(); String indexName = "IND_" + generateUniqueName(); String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName); + String fullIndexeName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName); // Check system tables priorities. try (HBaseAdmin admin = driver.getConnectionQueryServices(null, null).getAdmin(); Connection c = DriverManager.getConnection(getUrl())) { @@ -1107,7 +1130,7 @@ public abstract class BaseIndexIT extends ParallelStatsDisabledIT { if (!localIndex && mutable) { HTableDescriptor indexTable = admin.getTableDescriptor( - org.apache.hadoop.hbase.TableName.valueOf(indexName)); + org.apache.hadoop.hbase.TableName.valueOf(fullIndexeName)); val = indexTable.getValue("PRIORITY"); assertNotNull("PRIORITY is not set for table:" + indexTable, val); assertTrue(Integer.parseInt(val) >= PhoenixRpcSchedulerFactory.getIndexPriority(config)); @@ -1140,7 +1163,7 @@ public abstract class BaseIndexIT extends ParallelStatsDisabledIT { ddl += "(p1 desc, p2))"; } stmt.executeUpdate(ddl); - ddl = "CREATE "+ (localIndex ? "LOCAL " : "") + " INDEX " + fullIndexName + " on " + fullTableName + "(a)"; + ddl = "CREATE "+ (localIndex ? "LOCAL " : "") + " INDEX " + indexName + " on " + fullTableName + "(a)"; stmt.executeUpdate(ddl); // upsert a single row http://git-wip-us.apache.org/repos/asf/phoenix/blob/4d6dbf9c/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ChildViewsUseParentViewIndexIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ChildViewsUseParentViewIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ChildViewsUseParentViewIndexIT.java index 6c8f9e8..f3ee2cb 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ChildViewsUseParentViewIndexIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ChildViewsUseParentViewIndexIT.java @@ -29,7 +29,11 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.Properties; +import org.apache.hadoop.hbase.HConstants; import org.apache.phoenix.end2end.ParallelStatsDisabledIT; +import org.apache.phoenix.jdbc.PhoenixConnection; +import org.apache.phoenix.schema.PTable; +import org.apache.phoenix.util.PhoenixRuntime; import org.apache.phoenix.util.QueryUtil; import org.junit.Test; @@ -111,7 +115,8 @@ public class ChildViewsUseParentViewIndexIT extends ParallelStatsDisabledIT { // create child of parent view that should be able to use the parent's index String childViewDdl = "CREATE VIEW " + childViewName1 + " AS SELECT * FROM " + parentViewName + " WHERE A2 = 'Y'"; conn.createStatement().execute(childViewDdl); - + + PTable childViewPTable = PhoenixRuntime.getTableNoCache(conn, childViewName1); // create child of parent view that should *not* be able to use the parent's index String grandChildViewDdl1 = "CREATE VIEW " + childViewName2 + " AS SELECT * FROM " + childViewName1 + " WHERE A3 = 'Z'"; conn.createStatement().execute(grandChildViewDdl1); http://git-wip-us.apache.org/repos/asf/phoenix/blob/4d6dbf9c/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/DropColumnIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/DropColumnIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/DropColumnIT.java index 28aa1e9..e19284a 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/DropColumnIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/DropColumnIT.java @@ -17,7 +17,6 @@ */ package org.apache.phoenix.end2end.index; -import static org.apache.phoenix.util.PhoenixRuntime.TENANT_ID_ATTRIB; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -50,7 +49,6 @@ import org.apache.phoenix.query.QueryServices; import org.apache.phoenix.schema.ColumnNotFoundException; import org.apache.phoenix.schema.PColumn; import org.apache.phoenix.schema.PName; -import org.apache.phoenix.schema.PNameFactory; import org.apache.phoenix.schema.PTable; import org.apache.phoenix.schema.PTableImpl; import org.apache.phoenix.schema.PTableKey; @@ -411,119 +409,4 @@ public class DropColumnIT extends ParallelStatsDisabledIT { } } - @Test - public void testDroppingIndexedColDropsViewIndex() throws Exception { - helpTestDroppingIndexedColDropsViewIndex(false); - } - - @Test - public void testDroppingIndexedColDropsMultiTenantViewIndex() throws Exception { - helpTestDroppingIndexedColDropsViewIndex(true); - } - - public void helpTestDroppingIndexedColDropsViewIndex(boolean isMultiTenant) throws Exception { - Properties props = PropertiesUtil.deepCopy(TestUtil.TEST_PROPERTIES); - props.setProperty(TENANT_ID_ATTRIB, TENANT_ID); - try (Connection conn = getConnection(); - Connection viewConn = isMultiTenant ? getConnection(props) : conn ) { - String tableWithView = generateUniqueName(); - String viewOfTable = generateUniqueName(); - String viewIndex1 = generateUniqueName(); - String viewIndex2 = generateUniqueName(); - - conn.setAutoCommit(false); - viewConn.setAutoCommit(false); - String ddlFormat = "CREATE TABLE " + tableWithView + " (%s k VARCHAR NOT NULL, v1 VARCHAR, v2 VARCHAR, v3 VARCHAR, v4 VARCHAR CONSTRAINT PK PRIMARY KEY(%s k))%s"; - String ddl = String.format(ddlFormat, isMultiTenant ? "TENANT_ID VARCHAR NOT NULL, " : "", - isMultiTenant ? "TENANT_ID, " : "", isMultiTenant ? "MULTI_TENANT=true" : ""); - conn.createStatement().execute(ddl); - viewConn.createStatement() - .execute( - "CREATE VIEW " + viewOfTable + " ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR ) AS SELECT * FROM " + tableWithView ); - // create an index with the column that will be dropped - viewConn.createStatement().execute("CREATE INDEX " + viewIndex1 + " ON " + viewOfTable + "(v2) INCLUDE (v4)"); - // create an index without the column that will be dropped - viewConn.createStatement().execute("CREATE INDEX " + viewIndex2 + " ON " + viewOfTable + "(v1) INCLUDE (v4)"); - // verify index was created - try { - viewConn.createStatement().execute("SELECT * FROM " + viewIndex1 ); - } catch (TableNotFoundException e) { - fail("Index on view was not created"); - } - - // upsert a single row - PreparedStatement stmt = viewConn.prepareStatement("UPSERT INTO " + viewOfTable + " VALUES(?,?,?,?,?,?,?)"); - stmt.setString(1, "a"); - stmt.setString(2, "b"); - stmt.setString(3, "c"); - stmt.setString(4, "d"); - stmt.setString(5, "e"); - stmt.setInt(6, 1); - stmt.setString(7, "g"); - stmt.execute(); - viewConn.commit(); - - // verify the index was created - PhoenixConnection pconn = viewConn.unwrap(PhoenixConnection.class); - PName tenantId = isMultiTenant ? PNameFactory.newName("tenant1") : null; - PTable view = pconn.getTable(new PTableKey(tenantId, viewOfTable )); - PTable viewIndex = pconn.getTable(new PTableKey(tenantId, viewIndex1 )); - byte[] viewIndexPhysicalTable = viewIndex.getPhysicalName().getBytes(); - assertNotNull("Can't find view index", viewIndex); - assertEquals("Unexpected number of indexes ", 2, view.getIndexes().size()); - assertEquals("Unexpected index ", viewIndex1 , view.getIndexes().get(0).getName() - .getString()); - assertEquals("Unexpected index ", viewIndex2 , view.getIndexes().get(1).getName() - .getString()); - - // drop two columns - conn.createStatement().execute("ALTER TABLE " + tableWithView + " DROP COLUMN v2, v3 "); - - // verify columns were dropped - try { - conn.createStatement().execute("SELECT v2 FROM " + tableWithView ); - fail("Column should have been dropped"); - } catch (ColumnNotFoundException e) { - } - try { - conn.createStatement().execute("SELECT v3 FROM " + tableWithView ); - fail("Column should have been dropped"); - } catch (ColumnNotFoundException e) { - } - - // verify index metadata was dropped - try { - viewConn.createStatement().execute("SELECT * FROM " + viewIndex1 ); - fail("Index metadata should have been dropped"); - } catch (TableNotFoundException e) { - } - - pconn = viewConn.unwrap(PhoenixConnection.class); - view = pconn.getTable(new PTableKey(tenantId, viewOfTable )); - try { - viewIndex = pconn.getTable(new PTableKey(tenantId, viewIndex1 )); - fail("View index should have been dropped"); - } catch (TableNotFoundException e) { - } - assertEquals("Unexpected number of indexes ", 1, view.getIndexes().size()); - assertEquals("Unexpected index ", viewIndex2 , view.getIndexes().get(0).getName().getString()); - - // verify that the physical index view table is *not* dropped - conn.unwrap(PhoenixConnection.class).getQueryServices().getTableDescriptor(viewIndexPhysicalTable); - - // scan the physical table and verify there is a single row for the second local index - Scan scan = new Scan(); - HTable table = (HTable) conn.unwrap(PhoenixConnection.class).getQueryServices().getTable(viewIndexPhysicalTable); - ResultScanner results = table.getScanner(scan); - Result result = results.next(); - assertNotNull(result); - PTable viewIndexPTable = pconn.getTable(new PTableKey(pconn.getTenantId(), viewIndex2)); - PColumn column = viewIndexPTable.getColumnForColumnName(IndexUtil.getIndexColumnName(QueryConstants.DEFAULT_COLUMN_FAMILY, "V4")); - byte[] cq = column.getColumnQualifierBytes(); - // there should be a single row belonging to VIEWINDEX2 - assertNotNull(viewIndex2 + " row is missing", result.getValue(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, cq)); - assertNull(results.next()); - } - } - } http://git-wip-us.apache.org/repos/asf/phoenix/blob/4d6dbf9c/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexMetadataIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexMetadataIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexMetadataIT.java index 986c317..21fa312 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexMetadataIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexMetadataIT.java @@ -422,7 +422,7 @@ public class IndexMetadataIT extends ParallelStatsDisabledIT { Connection conn = DriverManager.getConnection(getUrl(), props); conn.setAutoCommit(false); try { - String ddl = "create table test_table (char_pk varchar not null," + String ddl = "create table " + generateUniqueName() + " (char_pk varchar not null," + " int_col integer, long_col integer, int_col integer" + " constraint pk primary key (char_pk))"; conn.createStatement().execute(ddl); @@ -440,7 +440,7 @@ public class IndexMetadataIT extends ParallelStatsDisabledIT { Connection conn = DriverManager.getConnection(getUrl(), props); conn.setAutoCommit(false); try { - String ddl = "create table test_table (char_pk varchar not null," + String ddl = "create table " + generateUniqueName() + " (char_pk varchar not null," + " a.int_col integer, a.long_col integer," + " a.int_col integer, b.long_col integer" + " constraint pk primary key (char_pk))";