PHOENIX-4669 NoSuchColumnFamilyException when creating index on views that are built on tables which have named column family
Signed-off-by: ss77892 <s...@apache.org> Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/c22e4c39 Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/c22e4c39 Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/c22e4c39 Branch: refs/heads/4.x-HBase-0.98 Commit: c22e4c39c60cee88930366d1544353dd7a87e037 Parents: a9ddf17 Author: Toshihiro Suzuki <brfrn...@gmail.com> Authored: Thu Mar 29 17:17:37 2018 +0900 Committer: ss77892 <s...@apache.org> Committed: Mon Apr 9 22:18:33 2018 -0700 ---------------------------------------------------------------------- .../phoenix/end2end/index/ViewIndexIT.java | 45 +++++++++++++++++++- .../query/ConnectionQueryServicesImpl.java | 27 ++++++------ 2 files changed, 57 insertions(+), 15 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/c22e4c39/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ViewIndexIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ViewIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ViewIndexIT.java index 53bb550..8ffd798 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ViewIndexIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ViewIndexIT.java @@ -31,6 +31,7 @@ import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Statement; import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -443,5 +444,47 @@ public class ViewIndexIT extends ParallelStatsDisabledIT { assertFalse(rs.next()); assertEquals(indexName, stmt.getQueryPlan().getContext().getCurrentTable().getTable().getName().getString()); } - + + @Test + public void testCreatingIndexOnViewBuiltOnTableWithOnlyNamedColumnFamilies() throws Exception { + try (Connection c = getConnection(); Statement s = c.createStatement()) { + String tableName = generateUniqueName(); + String viewName = generateUniqueName(); + String indexName = generateUniqueName(); + + c.setAutoCommit(true); + s.execute("CREATE TABLE " + tableName + " (COL1 VARCHAR PRIMARY KEY, CF.COL2 VARCHAR)"); + s.executeUpdate("UPSERT INTO " + tableName + " VALUES ('AAA', 'BBB')"); + s.execute("CREATE VIEW " + viewName + " AS SELECT * FROM " + tableName); + s.execute("CREATE INDEX " + indexName + " ON " + viewName + " (CF.COL2)"); + + try (ResultSet rs = s.executeQuery("SELECT * FROM " + viewName + " WHERE CF.COL2 = 'BBB'")) { + assertTrue(rs.next()); + assertEquals("AAA", rs.getString("COL1")); + assertEquals("BBB", rs.getString("COL2")); + } + } + try (Connection c = getConnection(); Statement s = c.createStatement()) { + String tableName = generateUniqueName(); + String viewName = generateUniqueName(); + String index1Name = generateUniqueName(); + String index2Name = generateUniqueName(); + + c.setAutoCommit(true); + s.execute("create table " + tableName + " (i1 integer primary key, c2.i2 integer, c3.i3 integer, c4.i4 integer)"); + s.execute("create view " + viewName + " as select * from " + tableName + " where c2.i2 = 1"); + s.executeUpdate("upsert into " + viewName + "(i1, c3.i3, c4.i4) VALUES (1, 1, 1)"); + s.execute("create index " + index1Name + " ON " + viewName + " (c3.i3)"); + s.execute("create index " + index2Name + " ON " + viewName + " (c3.i3) include (c4.i4)"); + s.executeUpdate("upsert into " + viewName + "(i1, c3.i3, c4.i4) VALUES (2, 2, 2)"); + + try (ResultSet rs = s.executeQuery("select * from " + viewName + " WHERE c3.i3 = 1")) { + assertTrue(rs.next()); + assertEquals(1, rs.getInt("i1")); + assertEquals(1, rs.getInt("i2")); + assertEquals(1, rs.getInt("i3")); + assertEquals(1, rs.getInt("i4")); + } + } + } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/c22e4c39/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java index 9c17f03..1989c54 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java @@ -1684,22 +1684,20 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement throws SQLException { byte[] physicalTableName = table.getPhysicalName().getBytes(); HTableDescriptor htableDesc = this.getTableDescriptor(physicalTableName); - Map<String,Object> tableProps = createPropertiesMap(htableDesc.getValues()); - List<Pair<byte[],Map<String,Object>>> families = Lists.newArrayListWithExpectedSize(Math.max(1, table.getColumnFamilies().size()+1)); - if (families.isEmpty()) { - byte[] familyName = SchemaUtil.getEmptyColumnFamily(table); + List<Pair<byte[],Map<String,Object>>> families = Lists.newArrayListWithExpectedSize(Math.max(1, table.getColumnFamilies().size() + 1)); + + // Create all column families that the parent table has + for (PColumnFamily family : table.getColumnFamilies()) { + byte[] familyName = family.getName().getBytes(); Map<String,Object> familyProps = createPropertiesMap(htableDesc.getFamily(familyName).getValues()); - families.add(new Pair<byte[],Map<String,Object>>(familyName, familyProps)); - } else { - for (PColumnFamily family : table.getColumnFamilies()) { - byte[] familyName = family.getName().getBytes(); - Map<String,Object> familyProps = createPropertiesMap(htableDesc.getFamily(familyName).getValues()); - families.add(new Pair<byte[],Map<String,Object>>(familyName, familyProps)); - } - // Always create default column family, because we don't know in advance if we'll - // need it for an index with no covered columns. - families.add(new Pair<byte[],Map<String,Object>>(table.getDefaultFamilyName().getBytes(), Collections.<String,Object>emptyMap())); + families.add(new Pair<>(familyName, familyProps)); } + // Always create default column family, because we don't know in advance if we'll + // need it for an index with no covered columns. + byte[] defaultFamilyName = table.getDefaultFamilyName() == null ? + QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES : table.getDefaultFamilyName().getBytes(); + families.add(new Pair<>(defaultFamilyName, Collections.<String,Object>emptyMap())); + byte[][] splits = null; if (table.getBucketNum() != null) { splits = SaltingUtil.getSalteByteSplitPoints(table.getBucketNum()); @@ -1707,6 +1705,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement // Transfer over table values into tableProps // TODO: encapsulate better + Map<String,Object> tableProps = createPropertiesMap(htableDesc.getValues()); tableProps.put(PhoenixDatabaseMetaData.TRANSACTIONAL, table.isTransactional()); tableProps.put(PhoenixDatabaseMetaData.IMMUTABLE_ROWS, table.isImmutableRows()); ensureViewIndexTableCreated(physicalTableName, tableProps, families, splits, timestamp, isNamespaceMapped);