This is an automated email from the ASF dual-hosted git repository.

tkhurana pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/phoenix.git


The following commit(s) were added to refs/heads/master by this push:
     new 5a3a4a8309 PHOENIX-7304 - Adding utilitiy method to get view index ids 
for given view index table (#2026)
5a3a4a8309 is described below

commit 5a3a4a83094b325fdaf5f08c94a53fbdfd3e8b61
Author: Himanshu Gwalani <[email protected]>
AuthorDate: Fri Nov 29 17:23:47 2024 +0530

    PHOENIX-7304 - Adding utilitiy method to get view index ids for given view 
index table (#2026)
    
    Adding utilitiy method to get view index ids
---
 .../java/org/apache/phoenix/util/ViewUtil.java     |  47 +++++++++
 .../org/apache/phoenix/end2end/ViewUtilIT.java     | 110 ++++++++++++++++++++-
 2 files changed, 153 insertions(+), 4 deletions(-)

diff --git 
a/phoenix-core-client/src/main/java/org/apache/phoenix/util/ViewUtil.java 
b/phoenix-core-client/src/main/java/org/apache/phoenix/util/ViewUtil.java
index 1f52bfa4bb..071bc20769 100644
--- a/phoenix-core-client/src/main/java/org/apache/phoenix/util/ViewUtil.java
+++ b/phoenix-core-client/src/main/java/org/apache/phoenix/util/ViewUtil.java
@@ -15,9 +15,13 @@
  */
 package org.apache.phoenix.util;
 
+import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.hadoop.hbase.CompareOperator;
 import org.apache.phoenix.coprocessorclient.MetaDataEndpointImplConstants;
+import org.apache.phoenix.schema.types.PSmallint;
 import org.apache.phoenix.thirdparty.com.google.common.base.Objects;
+import org.apache.phoenix.thirdparty.com.google.common.base.Preconditions;
 import org.apache.phoenix.thirdparty.com.google.common.collect.ImmutableList;
 import org.apache.phoenix.thirdparty.com.google.common.collect.Lists;
 import org.apache.phoenix.thirdparty.com.google.common.collect.Maps;
@@ -64,7 +68,10 @@ import org.slf4j.LoggerFactory;
 import javax.annotation.Nullable;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.sql.Types;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -993,4 +1000,44 @@ public class ViewUtil {
             }
         }
     }
+
+    /**
+     * Retrieves the list of unique view index ids from SYSTEM.CATALOG for a 
given view index table
+     * @param connection - Phoenix Connection
+     * @param tableName - physical table name (having prefix {@link 
MetaDataUtil#VIEW_INDEX_TABLE_PREFIX} of the view index table for which view 
index ids need to be retrieved
+     * @param includeTenantViewIndexes - true if tenant view indexes to be 
included otherwise false
+     * @return - list of view index ids
+     * @throws IOException
+     * @throws SQLException
+     */
+    public static List<String> getViewIndexIds(final PhoenixConnection 
connection, final String tableName, final boolean includeTenantViewIndexes)
+            throws IOException, SQLException {
+        Preconditions.checkArgument(MetaDataUtil.isViewIndex(tableName));
+        final List<String> viewIndexIdsString = new ArrayList<>();
+        final String viewIndexIdsQuery = getViewIndexIdsQuery(tableName, 
includeTenantViewIndexes);
+        logger.info(String.format("Query to get view index ids for %s with 
includeTenantViewIndexes as %b is %s", tableName, includeTenantViewIndexes, 
viewIndexIdsQuery));
+        PreparedStatement preparedStatement = 
connection.prepareStatement(viewIndexIdsQuery);
+        ResultSet resultSet = preparedStatement.executeQuery();
+        while (resultSet.next()) {
+            int viewIndexType = resultSet.getInt(2);
+            // Unless explicitly specified as BIGINT in view index data type, 
both "null" and SMALLINT data type are considered as SMALLINT
+            if(resultSet.wasNull() || viewIndexType == Types.SMALLINT) {
+                byte[] data = 
PSmallint.INSTANCE.toBytes(resultSet.getObject(1));
+                viewIndexIdsString.add(Hex.encodeHexString(data));
+            } else {
+                byte[] data = PLong.INSTANCE.toBytes(resultSet.getObject(1));
+                viewIndexIdsString.add(Hex.encodeHexString(data));
+            }
+        }
+        return viewIndexIdsString;
+    }
+
+    private static String getViewIndexIdsQuery(final String tableName, boolean 
includeTenantViewIndexes) {
+        String schema = 
SchemaUtil.getSchemaNameFromFullName(SchemaUtil.getParentTableNameFromIndexTable(tableName,
 MetaDataUtil.VIEW_INDEX_TABLE_PREFIX));
+        final String TABLE_SCHEM_FILTER = (!StringUtils.isEmpty(schema) ? " 
AND TABLE_SCHEM = '" + schema + "' " : " AND TABLE_SCHEM IS NULL ");
+        final String TENANT_ID_FILTER = (!includeTenantViewIndexes ? " AND 
TENANT_ID IS NULL " : " ");
+        final String GET_VIEW_INDEX_TABLE_QUERY = "SELECT DISTINCT TABLE_NAME 
FROM SYSTEM.CATALOG WHERE LINK_TYPE = 2 AND COLUMN_FAMILY = '" + tableName + "' 
" + TABLE_SCHEM_FILTER + TENANT_ID_FILTER;
+        final String GET_VIEW_INDEX_IDS_QUERY = "SELECT DISTINCT 
VIEW_INDEX_ID, VIEW_INDEX_ID_DATA_TYPE FROM SYSTEM.CATALOG WHERE VIEW_INDEX_ID 
IS NOT NULL AND TABLE_NAME IN ( " + GET_VIEW_INDEX_TABLE_QUERY + ") " + 
TABLE_SCHEM_FILTER + TENANT_ID_FILTER;
+        return GET_VIEW_INDEX_IDS_QUERY;
+    }
 }
diff --git 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewUtilIT.java 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewUtilIT.java
index 7bdd051b2d..919a71d306 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewUtilIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewUtilIT.java
@@ -26,16 +26,15 @@ import org.apache.phoenix.coprocessorclient.TableInfo;
 import org.apache.phoenix.jdbc.PhoenixConnection;
 import org.apache.phoenix.query.ConnectionQueryServices;
 import org.apache.phoenix.schema.PTable;
-import org.apache.phoenix.util.SchemaUtil;
-import org.apache.phoenix.util.TableViewFinderResult;
-import org.apache.phoenix.util.PropertiesUtil;
-import org.apache.phoenix.util.ViewUtil;
+import org.apache.phoenix.util.*;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
+import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.sql.Connection;
 import java.sql.DriverManager;
+import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Properties;
@@ -443,4 +442,107 @@ public class ViewUtilIT extends ParallelStatsDisabledIT {
         }
     }
 
+    /**
+     * Test {@link ViewUtil#getViewIndexIds(PhoenixConnection, String, 
boolean)} for a table which is not view index and ensure it throws {@link 
IllegalArgumentException}
+     * @throws IOException
+     * @throws SQLException
+     */
+    @Test(expected=IllegalArgumentException.class)
+    public void testGetViewIndexIdsForNonViewIndexTable() throws IOException, 
SQLException {
+        try (Connection conn = DriverManager.getConnection(getUrl())) {
+            ViewUtil.getViewIndexIds(conn.unwrap(PhoenixConnection.class), 
"TEST_TABLE", true);
+        }
+    }
+
+    /**
+     * Test {@link ViewUtil#getViewIndexIds(PhoenixConnection, String, 
boolean)} for a table with non-null schema
+     * @throws SQLException
+     * @throws IOException
+     */
+    @Test
+    public void testGetViewIndexIdsWithSchema() throws SQLException, 
IOException {
+        testGetViewIndexIds(generateUniqueName());
+    }
+
+    /**
+     * Test {@link ViewUtil#getViewIndexIds(PhoenixConnection, String, 
boolean)} for a table without schema
+     * @throws SQLException
+     * @throws IOException
+     */
+    @Test
+    public void testGetViewIndexIdsWithoutSchema() throws SQLException, 
IOException {
+        testGetViewIndexIds(null);
+    }
+
+    /**
+     * Helper method to test {@link 
ViewUtil#getViewIndexIds(PhoenixConnection, String, boolean)} method
+     * 1. Create a multi-tenant table
+     * 2. Create 2 global views (globalViewName1 & globalViewName2) and 5 
global view indexes (2 on globalViewName1 & 3 on globalViewName2)
+     * 3. Create 2 tenant views (tenantViewName1 & tenantViewName2) and 3 
tenant view indexes (1 on tenantViewName1 & 2 on tenantViewName2)
+     * 4. Get view index ids EXCLUDING tenant view indexes and ensure the 
count is 5 (5 global view indexes)
+     * 5. Get view index ids INCLUDING tenant view indexes and ensure the 
count is 8 (5 global view index + 3 tenant view indexes)
+     * @param schemaPrefix - schema name for the table, it can be null if no 
schema is to be used
+     * @throws IOException
+     * @throws SQLException
+     */
+    private void testGetViewIndexIds(String schemaPrefix) throws IOException, 
SQLException {
+        final String tableName = SchemaUtil.getTableName(schemaPrefix, 
generateUniqueName());
+        final String globalViewName1 = SchemaUtil.getTableName(schemaPrefix, 
generateUniqueName());
+        final String globalViewName2 = SchemaUtil.getTableName(schemaPrefix, 
generateUniqueName());
+        final String globalViewIndex11 = generateUniqueName() + "_INDEX11";
+        final String globalViewIndex12 = generateUniqueName() + "_INDEX12";
+        final String globalViewIndex21 = generateUniqueName() + "_INDEX21";
+        final String globalViewIndex22 = generateUniqueName() + "_INDEX22";
+        final String globalViewIndex23 = generateUniqueName() + "_INDEX23";
+
+        final String tenantId = generateUniqueName();
+        Properties tenantProps = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+        tenantProps.setProperty(TENANT_ID_ATTRIB, tenantId);
+        final String tenantViewName1 = SchemaUtil.getTableName(schemaPrefix, 
generateUniqueName());
+        final String tenantViewName2 = SchemaUtil.getTableName(schemaPrefix, 
generateUniqueName());
+        final String tenantViewIndex11 = generateUniqueName() + "_INDEX11";
+        final String tenantViewIndex21 = generateUniqueName() + "_INDEX21";
+        final String tenantViewIndex22 = generateUniqueName() + "_INDEX22";
+
+        final String createTableDDL = "CREATE TABLE " + tableName +
+                "(TENANT_ID CHAR(10) NOT NULL, ID CHAR(10) NOT NULL, NUM 
BIGINT " +
+                "CONSTRAINT PK PRIMARY KEY (TENANT_ID, ID)) MULTI_TENANT=true";
+        final String globalViewDDL = "CREATE VIEW %s (PK1 BIGINT, PK2 BIGINT) 
" +
+                "AS SELECT * FROM " + tableName + " WHERE NUM > -1";
+        final String viewIndexDDL = "CREATE INDEX %s ON %s (NUM DESC) INCLUDE 
(ID)";
+        final String tenantViewDDL = "CREATE VIEW %s AS SELECT * FROM %s";
+
+        try (Connection conn = DriverManager.getConnection(getUrl())) {
+
+            // Create data table, global views and global view indexes
+            conn.createStatement().execute(createTableDDL);
+            conn.createStatement().execute(String.format(globalViewDDL, 
globalViewName1));
+            conn.createStatement().execute(String.format(globalViewDDL, 
globalViewName2));
+            conn.createStatement().execute(String.format(viewIndexDDL, 
globalViewIndex11, globalViewName1));
+            conn.createStatement().execute(String.format(viewIndexDDL, 
globalViewIndex12, globalViewName1));
+            conn.createStatement().execute(String.format(viewIndexDDL, 
globalViewIndex21, globalViewName2));
+            conn.createStatement().execute(String.format(viewIndexDDL, 
globalViewIndex22, globalViewName2));
+            conn.createStatement().execute(String.format(viewIndexDDL, 
globalViewIndex23, globalViewName2));
+
+
+            // Create tenant views and tenant view indexes
+            try (Connection tenantConn = DriverManager.getConnection(getUrl(), 
tenantProps)) {
+                tenantConn.createStatement().execute(
+                        String.format(tenantViewDDL, tenantViewName1, 
tableName));
+                tenantConn.createStatement().execute(
+                        String.format(tenantViewDDL, tenantViewName2, 
tableName));
+                
tenantConn.createStatement().execute(String.format(viewIndexDDL, 
tenantViewIndex11, tenantViewName1));
+                
tenantConn.createStatement().execute(String.format(viewIndexDDL, 
tenantViewIndex21, tenantViewName2));
+                
tenantConn.createStatement().execute(String.format(viewIndexDDL, 
tenantViewIndex22, tenantViewName2));
+            }
+
+            // Get view indexes ids only for global view indexes (excluding 
tenant view indexes)
+            List<String> list = 
ViewUtil.getViewIndexIds(conn.unwrap(PhoenixConnection.class), 
MetaDataUtil.getViewIndexPhysicalName(tableName), false);
+            assertEquals(5, list.size());
+
+            // Get view indexes ids for both global and tenant view indexes
+            list = 
ViewUtil.getViewIndexIds(conn.unwrap(PhoenixConnection.class), 
MetaDataUtil.getViewIndexPhysicalName(tableName), true);
+            assertEquals(8, list.size());
+        }
+    }
 }

Reply via email to