Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,7 +18,7 @@
package org.apache.phoenix.end2end;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.sql.Connection;
Expand All@@ -31,6 +31,7 @@
import org.apache.phoenix.jdbc.PhoenixConnection;
import org.apache.phoenix.query.QueryServices;
import org.apache.phoenix.schema.SchemaAlreadyExistsException;
import org.apache.phoenix.util.ServerUtil;
import org.apache.phoenix.util.PropertiesUtil;
import org.apache.phoenix.util.SchemaUtil;
import org.apache.phoenix.util.TestUtil;
Expand All@@ -47,7 +48,7 @@ public void testCreateSchema() throws Exception {
try (Connection conn = DriverManager.getConnection(getUrl(), props);
Admin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin();) {
conn.createStatement().execute(ddl);
assertNotNull(admin.getNamespaceDescriptor(schemaName));
assertTrue(ServerUtil.isHbaseNamespaceAvailable(admin, schemaName));
}
try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
conn.createStatement().execute(ddl);
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,7 +18,7 @@
package org.apache.phoenix.end2end;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.sql.Connection;
Expand All@@ -30,12 +30,12 @@
import java.util.Properties;

import org.apache.hadoop.hbase.NamespaceDescriptor;
import org.apache.hadoop.hbase.NamespaceNotFoundException;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.phoenix.exception.SQLExceptionCode;
import org.apache.phoenix.jdbc.PhoenixConnection;
import org.apache.phoenix.query.QueryServices;
import org.apache.phoenix.schema.SchemaNotFoundException;
import org.apache.phoenix.util.ServerUtil;
import org.apache.phoenix.util.ReadOnlyProps;
import org.apache.phoenix.util.SchemaUtil;
import org.junit.BeforeClass;
Expand DownExpand Up@@ -92,22 +92,18 @@ public void testDropSchema() throws Exception {
} catch (SQLException e) {
assertEquals(e.getErrorCode(), SQLExceptionCode.CANNOT_MUTATE_SCHEMA.getErrorCode());
}
assertNotNull(admin.getNamespaceDescriptor(normalizeSchemaIdentifier));
assertTrue(ServerUtil.isHbaseNamespaceAvailable(admin, normalizeSchemaIdentifier));

conn.createStatement().execute("DROP TABLE " + schema + "." + tableName);
conn.createStatement().execute(ddl);
try {
admin.getNamespaceDescriptor(normalizeSchemaIdentifier);
if(ServerUtil.isHbaseNamespaceAvailable(admin, normalizeSchemaIdentifier))
fail();
} catch (NamespaceNotFoundException ne) {
// expected
}

conn.createStatement().execute("DROP SCHEMA IF EXISTS " + schema);

admin.createNamespace(NamespaceDescriptor.create(normalizeSchemaIdentifier).build());
conn.createStatement().execute("DROP SCHEMA IF EXISTS " + schema);
assertNotNull(admin.getNamespaceDescriptor(normalizeSchemaIdentifier));
assertTrue(ServerUtil.isHbaseNamespaceAvailable(admin, normalizeSchemaIdentifier));
conn.createStatement().execute("CREATE SCHEMA " + schema);
conn.createStatement().execute("DROP SCHEMA " + schema);
try {
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -46,7 +46,6 @@
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.NamespaceNotFoundException;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.phoenix.compat.hbase.CompatUtil;
Expand All@@ -62,6 +61,7 @@
import org.apache.phoenix.query.QueryConstants;
import org.apache.phoenix.query.QueryServices;
import org.apache.phoenix.query.QueryServicesTestImpl;
import org.apache.phoenix.util.ServerUtil;
import org.apache.phoenix.util.ReadOnlyProps;
import org.apache.phoenix.util.UpgradeUtil;
import org.junit.After;
Expand DownExpand Up@@ -570,12 +570,7 @@ private Set<String> getHBaseTables() throws IOException {

// Check if the SYSTEM namespace has been created
private boolean isSystemNamespaceCreated() throws IOException {
try {
testUtil.getAdmin().getNamespaceDescriptor(SYSTEM_CATALOG_SCHEMA);
} catch (NamespaceNotFoundException ex) {
return false;
}
return true;
return ServerUtil.isHbaseNamespaceAvailable(testUtil.getConnection().getAdmin(), SYSTEM_CATALOG_SCHEMA);
}

/**
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,8 @@
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.Get;
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.client.Table;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.replication.ChainWALEntryFilter;
Expand All@@ -37,6 +39,7 @@
import org.apache.hadoop.hbase.wal.WALEdit;
import org.apache.hadoop.hbase.wal.WALKeyImpl;
import org.apache.phoenix.end2end.ParallelStatsDisabledIT;
import org.apache.phoenix.hbase.index.wal.IndexedKeyValue;
import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData;
import org.apache.phoenix.mapreduce.util.ConnectionUtil;
import org.apache.phoenix.schema.PTable;
Expand DownExpand Up@@ -71,8 +74,8 @@ public class SystemCatalogWALEntryFilterIT extends ParallelStatsDisabledIT {
+ NONTENANT_VIEW_NAME + "(" + VIEW_COLUMN_NAME + " varchar) AS SELECT * FROM "
+ TestUtil.ENTITY_HISTORY_TABLE_NAME + " WHERE OLD_VALUE like 'E%'";

private static final String DROP_TENANT_VIEW_SQL = "DROP VIEW IF EXISTS " + TENANT_VIEW_NAME;
private static final String DROP_NONTENANT_VIEW_SQL = "DROP VIEW IF EXISTS " + NONTENANT_VIEW_NAME;
private static final String DROP_TENANT_VIEW_SQL = "DROP VIEW IF EXISTS " + SCHEMA_NAME + "." + TENANT_VIEW_NAME;
private static final String DROP_NONTENANT_VIEW_SQL = "DROP VIEW IF EXISTS " + SCHEMA_NAME + "." + NONTENANT_VIEW_NAME;
private static PTable catalogTable;
private static PTable childLinkTable;
private static WALKeyImpl walKeyCatalog = null;
Expand DownExpand Up@@ -100,24 +103,13 @@ public static synchronized void setup() throws Exception {
PhoenixDatabaseMetaData.SYSTEM_CHILD_LINK_NAME), 0, 0, uuid);
};
Assert.assertNotNull(catalogTable);
try (java.sql.Connection connection =
ConnectionUtil.getInputConnection(getUtility().getConfiguration(), new Properties())) {
connection.createStatement().execute(CREATE_NONTENANT_VIEW_SQL);
};
createNonTenantView();
}

@AfterClass
public static synchronized void tearDown() throws Exception {
Properties tenantProperties = new Properties();
tenantProperties.setProperty("TenantId", TENANT_ID);
try (java.sql.Connection connection =
ConnectionUtil.getInputConnection(getUtility().getConfiguration(), tenantProperties)) {
connection.createStatement().execute(DROP_TENANT_VIEW_SQL);
}
try (java.sql.Connection connection =
ConnectionUtil.getInputConnection(getUtility().getConfiguration(), new Properties())) {
connection.createStatement().execute(DROP_NONTENANT_VIEW_SQL);
}
dropTenantView();
dropNonTenantView();
}

@Test
Expand All@@ -139,7 +131,7 @@ public void testSystemCatalogWALEntryFilter() throws Exception {

WAL.Entry nonTenantEntryCatalog = getEntry(systemCatalogTableName, nonTenantGetCatalog);
WAL.Entry tenantEntryCatalog = getEntry(systemCatalogTableName, tenantGetCatalog);
int tenantRowCount = getAndAssertTenantCountInEdit(tenantEntryCatalog);
int tenantRowCount = getAndAssertCountInEdit(tenantEntryCatalog, true);
Assert.assertTrue(tenantRowCount > 0);

//verify that the tenant view WAL.Entry passes the filter and the non-tenant view does not
Expand All@@ -156,7 +148,7 @@ public void testSystemCatalogWALEntryFilter() throws Exception {
Assert.assertNotNull("Tenant view was filtered when it shouldn't be!",
filteredTenantEntryCatalog);
Assert.assertEquals("Not all data for replicated for tenant", tenantRowCount,
getAndAssertTenantCountInEdit(filteredTenantEntryCatalog));
getAndAssertCountInEdit(filteredTenantEntryCatalog, true));

//now check that a WAL.Entry with cells from both a tenant and a non-tenant
//catalog row only allow the tenant cells through
Expand All@@ -182,7 +174,7 @@ public void testSystemChildLinkWALEntryFilter() throws Exception {

WAL.Entry tenantEntryChildLink = getEntry(systemChildLinkTableName, tenantGetChildLink);
WAL.Entry nonTenantEntryChildLink = getEntry(systemChildLinkTableName, nonTenantGetChildLink);
int tenantRowCount = getAndAssertTenantCountInEdit(tenantEntryChildLink);
int tenantRowCount = getAndAssertCountInEdit(tenantEntryChildLink, true);
Assert.assertTrue(tenantRowCount > 0);

//verify that the tenant view WAL.Entry passes the filter and the non-tenant view does not
Expand All@@ -199,7 +191,7 @@ public void testSystemChildLinkWALEntryFilter() throws Exception {
Assert.assertNotNull("Tenant view was filtered when it shouldn't be!",
filteredTenantEntryChildLink);
Assert.assertEquals("Not all data for replicated for tenant", tenantRowCount,
getAndAssertTenantCountInEdit(filteredTenantEntryChildLink));
getAndAssertCountInEdit(filteredTenantEntryChildLink, true));

//now check that a WAL.Entry with cells from both a tenant and a non-tenant
// child link row only allow the tenant cells through
Expand All@@ -214,7 +206,49 @@ public void testSystemChildLinkWALEntryFilter() throws Exception {
chainWALEntryFilter.filter(comboEntry).getEdit().size());
}

public Get getGet(PTable catalogTable, byte[] tenantId, String viewName) {
/**
* Validates the behavior for parent-child link's delete marker via SystemCatalogWalEntryFilter.
* 1. Filtered for non-tenant views.
* 2. Not filtered for tenant views.
* */
@Test
public void testDeleteMarkerForParentChildLink() throws Exception{
// Since for 4.16+ all parent-child links are stored in SYSTEM.CHILD_LINK, only
// checking for that table in this test.

// Make sure link row exists.
WAL.Entry childLinkEntry = getEntry(systemChildLinkTableName, new Scan(),
false);
int tenantRowCount = getAndAssertCountInEdit(childLinkEntry, true);
int nonTenantRowCount = getAndAssertCountInEdit(childLinkEntry, false);
Assert.assertTrue(tenantRowCount > 0 && nonTenantRowCount > 0 );

// Drop both tenant and non-tenant view.
dropTenantView();
dropNonTenantView();

// Delete Marker for non-tenant view should get filtered and for tenant-view it should not.
SystemCatalogWALEntryFilter filter = new SystemCatalogWALEntryFilter();
// Chain the system catalog WAL entry filter to ChainWALEntryFilter
ChainWALEntryFilter chainWALEntryFilter = new ChainWALEntryFilter(filter);
childLinkEntry = getEntry(systemChildLinkTableName, new Scan(),
false);
int tenantDeleteCountBeforeFilter = getDeleteFamilyCellCountInEntry(childLinkEntry, true);
int nonTenantDeleteCountBeforeFilter = getDeleteFamilyCellCountInEntry(childLinkEntry, false);
// Make sure both tenant and non-tenant delete marker exists before filtering
Assert.assertTrue(tenantDeleteCountBeforeFilter > 0 && nonTenantDeleteCountBeforeFilter > 0 );

WAL.Entry filteredEntry = chainWALEntryFilter.filter(childLinkEntry);
int tenantDeleteCountAfterFilter = getDeleteFamilyCellCountInEntry(filteredEntry, true);
int nonTenantDeleteCountAfterFilter = getDeleteFamilyCellCountInEntry(filteredEntry, false);
Assert.assertTrue(tenantDeleteCountAfterFilter == tenantDeleteCountBeforeFilter && nonTenantDeleteCountAfterFilter == 0 );

// setup views again.
createTenantView();
createNonTenantView();
}

private Get getGet(PTable catalogTable, byte[] tenantId, String viewName) {
byte[][] tenantKeyParts = new byte[5][];
tenantKeyParts[0] = tenantId;
tenantKeyParts[1] = Bytes.toBytes(SCHEMA_NAME.toUpperCase());
Expand All@@ -228,7 +262,7 @@ public Get getGet(PTable catalogTable, byte[] tenantId, String viewName) {
return new Get(key.copyBytes());
}

public Get getGetChildLink(PTable catalogTable, byte[] tenantId, String viewName) {
private Get getGetChildLink(PTable catalogTable, byte[] tenantId, String viewName) {
byte[][] tenantKeyParts = new byte[5][];
tenantKeyParts[0] = ByteUtil.EMPTY_BYTE_ARRAY;
tenantKeyParts[1] = ByteUtil.EMPTY_BYTE_ARRAY;
Expand All@@ -249,21 +283,53 @@ private boolean isTenantOwnedCell(Cell cell, String tenantId) {
boolean isChildLinkForTenantId = row.contains(tenantId)
&& CellUtil.matchingQualifier(cell,
PhoenixDatabaseMetaData.LINK_TYPE_BYTES);
return isTenantIdLeading || isChildLinkForTenantId;
boolean isDeleteMarkerForLinkRow = row.contains(tenantId) && CellUtil.isDeleteFamily(cell);
return isTenantIdLeading || isChildLinkForTenantId || isDeleteMarkerForLinkRow;
}

private int getAndAssertTenantCountInEdit(WAL.Entry entry) {
int count = 0;
/**
* Asserts and returns cell count in the WAL.Entry. if tenantOwned is true, tenant owned cell count is
* returned else non-tenant cell count.
* @Param entry {@link WAL.Entry}
* @Param tenantOwned {@link Boolean}
* */
private int getAndAssertCountInEdit(WAL.Entry entry, boolean tenantOwned) {
int tenantCount = 0;
int nonTenantCount = 0;
for (Cell cell : entry.getEdit().getCells()) {
if (isTenantOwnedCell(cell, TENANT_ID)) {
count = count + 1;
tenantCount = tenantCount + 1;
} else {
nonTenantCount = nonTenantCount + 1;
}
}
int count = tenantOwned ? tenantCount : nonTenantCount;
Assert.assertTrue(count > 0);
return count;
}

public WAL.Entry getEntry(TableName tableName, Get get) throws IOException {
/**
* Returns delete family cell count in the WAL.Entry. if tenantOwned is true, tenant owned cell count is
* returned else non-tenant cell count.
* @Param entry {@link WAL.Entry}
* @Param tenantOwned {@link Boolean}
* */
private int getDeleteFamilyCellCountInEntry(WAL.Entry entry, boolean tenantOwned) {
int tenantCount = 0;
int nonTenantCount = 0;
for (Cell cell : entry.getEdit().getCells()) {
if (CellUtil.isDeleteFamily(cell)) {
if (isTenantOwnedCell(cell, TENANT_ID)) {
tenantCount = tenantCount + 1;
} else {
nonTenantCount = nonTenantCount + 1;
}
}
}
return tenantOwned ? tenantCount : nonTenantCount;
}

private WAL.Entry getEntry(TableName tableName, Get get) throws IOException {
WAL.Entry entry = null;
try(Connection conn = ConnectionFactory.createConnection(getUtility().getConfiguration())){
Table htable = conn.getTable(tableName);
Expand All@@ -284,4 +350,68 @@ public WAL.Entry getEntry(TableName tableName, Get get) throws IOException {
}
return entry;
}

private WAL.Entry getEntry(TableName tableName, Scan scan, boolean addIndexedKeyValueCell)
throws IOException {
WAL.Entry entry = null;
try(Connection conn = ConnectionFactory.createConnection(getUtility().getConfiguration())) {
Table htable = conn.getTable(tableName);
scan.setRaw(true);
ResultScanner scanner = htable.getScanner(scan);
WALEdit edit = new WALEdit();
if (addIndexedKeyValueCell) {
// add IndexedKeyValue type cell as the first cell
edit.add(new IndexedKeyValue());
}

for (Result r : scanner) {
if (r != null) {
List<Cell> cellList = r.listCells();
for (Cell c : cellList) {
edit.add(c);
}
}
}
Assert.assertFalse("No WALEdits were loaded!", edit.isEmpty());
WALKeyImpl key = new WALKeyImpl(REGION, tableName, 0, 0, uuid);
entry = new WAL.Entry(key, edit);
}
return entry;
}

private static void dropTenantView() throws Exception {
Properties tenantProperties = new Properties();
tenantProperties.setProperty("TenantId", TENANT_ID);
try (java.sql.Connection connection =
ConnectionUtil.getInputConnection(getUtility().getConfiguration(), tenantProperties)) {
connection.createStatement().execute(DROP_TENANT_VIEW_SQL);
connection.commit();
}
}

private static void dropNonTenantView() throws Exception {
try (java.sql.Connection connection =
ConnectionUtil.getInputConnection(getUtility().getConfiguration(), new Properties())) {

connection.createStatement().execute(DROP_NONTENANT_VIEW_SQL);
}
}

private static void createTenantView() throws Exception {
Properties tenantProperties = new Properties();
tenantProperties.setProperty("TenantId", TENANT_ID);
try (java.sql.Connection connection =
ConnectionUtil.getInputConnection(getUtility().getConfiguration(), tenantProperties)) {
connection.createStatement().execute(CREATE_TENANT_VIEW_SQL);
connection.commit();
}
}

private static void createNonTenantView() throws Exception {
try (java.sql.Connection connection =
ConnectionUtil.getInputConnection(getUtility().getConfiguration(), new Properties())) {
connection.createStatement().execute(CREATE_NONTENANT_VIEW_SQL);
connection.commit();
}
}
}
Loading