/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.phoenix.end2end;

import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.KeepDeletedCells;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.Pair;
import org.apache.phoenix.exception.SQLExceptionCode;
import org.apache.phoenix.jdbc.PhoenixConnection;
import org.apache.phoenix.schema.PName;
import org.apache.phoenix.schema.PTable;
import org.apache.phoenix.schema.PTableType;
import org.apache.phoenix.util.MetaDataUtil;
import org.apache.phoenix.util.PhoenixRuntime;
import org.apache.phoenix.util.SchemaUtil;
import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.apache.phoenix.query.QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES;
import static org.apache.phoenix.util.MetaDataUtil.SYNCED_DATA_TABLE_AND_INDEX_COL_FAM_PROPERTIES;
import static org.apache.phoenix.util.MetaDataUtil.VIEW_INDEX_TABLE_PREFIX;
import static org.apache.phoenix.util.UpgradeUtil.UPSERT_UPDATE_CACHE_FREQUENCY;
import static org.apache.phoenix.util.UpgradeUtil.syncTableAndIndexProperties;
import static org.apache.phoenix.util.UpgradeUtil.syncUpdateCacheFreqAllIndexes;
import static org.apache.phoenix.end2end.index.IndexMetadataIT.assertUpdateCacheFreq;

/**
 * Test properties that need to be kept in sync amongst all column families and indexes of a table
 */
public class PropertiesInSyncIT extends ParallelStatsDisabledIT {
    private static final String COL_FAM1 = "CF1";
    private static final String COL_FAM2 = "CF2";
    private static final String NEW_CF = "NEW_CF";
    private static final String DUMMY_PROP_VALUE = "dummy";
    private static final int INITIAL_TTL_VALUE = 700;
    private static final KeepDeletedCells INITIAL_KEEP_DELETED_CELLS_VALUE = KeepDeletedCells.TRUE;
    private static final int INITIAL_REPLICATION_SCOPE_VALUE = 1;
    private static final int INITIAL_UPDATE_CACHE_FREQUENCY = 100;
    private static final int INITIAL_UPDATE_CACHE_FREQUENCY_VIEWS = 900;
    private static final int MODIFIED_TTL_VALUE = INITIAL_TTL_VALUE + 300;
    private static final KeepDeletedCells MODIFIED_KEEP_DELETED_CELLS_VALUE =
            (INITIAL_KEEP_DELETED_CELLS_VALUE == KeepDeletedCells.TRUE) ?
                    KeepDeletedCells.FALSE: KeepDeletedCells.TRUE;
    private static final int MODIFIED_REPLICATION_SCOPE_VALUE =
            (INITIAL_REPLICATION_SCOPE_VALUE == 1) ? 0 : 1;
    private static final int MODIFIED_UPDATE_CACHE_FREQUENCY = INITIAL_UPDATE_CACHE_FREQUENCY + 300;
    private static final int MODIFIED_UPDATE_CACHE_FREQUENCY_VIEWS = INITIAL_UPDATE_CACHE_FREQUENCY_VIEWS + 300;


    // Test that we disallow specifying synced properties to be set per column family
    // when creating a table
    @Test
    public void testDisallowSyncedPropsToBeSetColFamSpecificCreateTable() throws Exception {
        Connection conn = DriverManager.getConnection(getUrl(), new Properties());
        String tableName = generateUniqueName();
        for (String propName: SYNCED_DATA_TABLE_AND_INDEX_COL_FAM_PROPERTIES) {
            try {
                conn.createStatement().execute("create table " + tableName
                        + " (id INTEGER not null primary key, "
                        + COL_FAM1 + ".name varchar(10), " + COL_FAM2 + ".flag boolean) "
                        + COL_FAM1 + "." + propName + "=" + DUMMY_PROP_VALUE);
                fail("Should fail with SQLException when setting synced property for"
                        + " a specific column family");
            } catch (SQLException sqlE) {
                assertEquals("Should fail to set synced property for a specific column family",
                        SQLExceptionCode.COLUMN_FAMILY_NOT_ALLOWED_FOR_PROPERTY.getErrorCode(),
                        sqlE.getErrorCode());
            }
        }
        conn.close();
    }

    // Test that all column families have the same value of synced properties when creating a table
    @Test
    public void testSyncedPropsAllColFamsCreateTable() throws Exception {
        Connection conn = DriverManager.getConnection(getUrl(), new Properties());
        String tableName = createBaseTableWithProps(conn);
        verifyHBaseColumnFamilyProperties(tableName, conn, false, false);
        conn.close();
    }

    // Test that we disallow specifying synced properties to be set when creating an index
    // on a physical table or a view
    @Test
    public void testDisallowSyncedPropsToBeSetCreateIndex() throws Exception {
        Connection conn = DriverManager.getConnection(getUrl(), new Properties());
        String tableName = createBaseTableWithProps(conn);
        String localIndexName = tableName + "_LOCAL_IDX";
        String globalIndexName = tableName + "_GLOBAL_IDX";
        String viewName = "VIEW_" + tableName;
        conn.createStatement().execute("create view " + viewName
                + " (new_col SMALLINT) as select * from " + tableName + " where id > 1");
        for (String propName: SYNCED_DATA_TABLE_AND_INDEX_COL_FAM_PROPERTIES) {
            try {
                conn.createStatement().execute("create local index " + localIndexName
                        + " on " + tableName + "(name) "
                        + propName + "=" + DUMMY_PROP_VALUE);
                fail("Should fail with SQLException when setting synced property for "
                        + "a local index");
            } catch (SQLException sqlE) {
                assertEquals("Should fail to set synced property for a local index",
                        SQLExceptionCode.CANNOT_SET_OR_ALTER_PROPERTY_FOR_INDEX.getErrorCode(),
                        sqlE.getErrorCode());
            }
            try {
                conn.createStatement().execute("create index " + globalIndexName
                        + " on " + tableName + "(flag) "
                        + propName + "=" + DUMMY_PROP_VALUE);
                fail("Should fail with SQLException when setting synced property for"
                        + " a global index");
            } catch (SQLException sqlE) {
                assertEquals("Should fail to set synced property for a global index",
                        SQLExceptionCode.CANNOT_SET_OR_ALTER_PROPERTY_FOR_INDEX.getErrorCode(),
                        sqlE.getErrorCode());
            }
            try {
                conn.createStatement().execute("create index view_index"
                        + " on " + viewName + " (flag)" + propName + "=" + DUMMY_PROP_VALUE);
                fail("Should fail with SQLException when setting synced property for a view index");
            } catch (SQLException sqlE) {
                assertEquals("Should fail to set synced property for a view index",
                        SQLExceptionCode.CANNOT_SET_OR_ALTER_PROPERTY_FOR_INDEX.getErrorCode(),
                        sqlE.getErrorCode());
            }
        }
        conn.close();
    }

    // Test that indexes have the same value of synced properties as their base table
    @Test
    public void testSyncedPropsBaseTableCreateIndex() throws Exception {
        Connection conn = DriverManager.getConnection(getUrl(), new Properties());
        String tableName = createBaseTableWithProps(conn);
        createIndexTable(conn, tableName, PTable.IndexType.LOCAL).getSecond();
        String globalIndexName = createIndexTable(conn, tableName, PTable.IndexType.GLOBAL).getSecond();

        // We pass the base table as the physical HBase table since our check includes checking
        // the local index column family too
        verifyHBaseColumnFamilyProperties(tableName, conn, false, false);
        verifyHBaseColumnFamilyProperties(globalIndexName, conn, false, false);
        conn.close();
    }

    // Test that the physical view index table has the same value of synced properties
    // as its base table
    @Test
    public void testSyncedPropsBaseTableCreateViewIndex() throws Exception {
        Connection conn = DriverManager.getConnection(getUrl(), new Properties());
        String tableName = createBaseTableWithProps(conn);
        String viewIndexName = createIndexTable(conn, tableName, null).getSecond();

        verifyHBaseColumnFamilyProperties(tableName, conn, false, false);
        verifyHBaseColumnFamilyProperties(viewIndexName, conn, false, false);
        conn.close();
    }

    // Test that we disallow specifying synced properties to be set per column family
    // when altering a table
    @Test
    public void testDisallowSyncedPropsToBeSetColFamSpecificAlterTable() throws Exception {
        Connection conn = DriverManager.getConnection(getUrl(), new Properties());
        String tableName = createBaseTableWithProps(conn);
        StringBuilder alterAllSyncedPropsString = new StringBuilder();
        String modPropString = COL_FAM1 + ".%s=" + DUMMY_PROP_VALUE + ",";
        for (String propName: SYNCED_DATA_TABLE_AND_INDEX_COL_FAM_PROPERTIES) {
            try {
                conn.createStatement().execute("alter table " + tableName
                        + " set " + COL_FAM1 + "." + propName + "=" + DUMMY_PROP_VALUE);
                fail("Should fail with SQLException when altering synced property for a"
                        + " specific column family");
            } catch (SQLException sqlE) {
                assertEquals("Should fail to alter synced property for a specific column family",
                        SQLExceptionCode.COLUMN_FAMILY_NOT_ALLOWED_FOR_PROPERTY.getErrorCode(),
                        sqlE.getErrorCode());
            }
            alterAllSyncedPropsString.append(String.format(modPropString, propName));
        }

        // Test the same when we try to set all of these properties at once
        try {
            conn.createStatement().execute("alter table " + tableName + " set "
                    + alterAllSyncedPropsString.substring(0, alterAllSyncedPropsString.length() - 1));
            fail("Should fail with SQLException when altering synced properties for a"
                    + " specific column family");
        } catch (SQLException sqlE) {
            assertEquals("Should fail to alter synced properties for a specific column family",
                    SQLExceptionCode.COLUMN_FAMILY_NOT_ALLOWED_FOR_PROPERTY.getErrorCode(),
                    sqlE.getErrorCode());
        }
        conn.close();
    }

    // Test that any alteration of the synced properties gets propagated to all indexes and
    // the physical view index table
    @Test
    public void testAlterSyncedPropsPropagateToAllIndexesAndViewIndex() throws Exception {
        Connection conn = DriverManager.getConnection(getUrl(), new Properties());
        String tableName = createBaseTableWithProps(conn);
        Set<String> tablesToCheck = new HashSet<>();
        tablesToCheck.add(tableName);
        for (int i=0; i<2; i++) {
            tablesToCheck.add(createIndexTable(conn, tableName, PTable.IndexType.LOCAL).getSecond());
            tablesToCheck.add(createIndexTable(conn, tableName, PTable.IndexType.GLOBAL).getSecond());
        }
        // Create a view and view index
        tablesToCheck.add(createIndexTable(conn, tableName, null).getSecond());

        // Now alter the base table's properties. This should get propagated to all index tables
        conn.createStatement().execute("alter table " + tableName + " set TTL=" + MODIFIED_TTL_VALUE
                + ",KEEP_DELETED_CELLS=" + MODIFIED_KEEP_DELETED_CELLS_VALUE
                + ",REPLICATION_SCOPE=" + MODIFIED_REPLICATION_SCOPE_VALUE);

        for (String table: tablesToCheck) {
            verifyHBaseColumnFamilyProperties(table, conn, true, false);
        }

        // Any indexes created henceforth should have the modified properties
        String newGlobalIndex = createIndexTable(conn, tableName, PTable.IndexType.GLOBAL).getSecond();
        String newViewIndex = createIndexTable(conn, tableName, null).getSecond();
        verifyHBaseColumnFamilyProperties(newGlobalIndex, conn, true, false);
        verifyHBaseColumnFamilyProperties(newViewIndex, conn, true, false);
        conn.close();
    }

    // Test that any if we add a column family to a base table, it gets the synced properties
    @Test
    public void testAlterTableAddColumnFamilyGetsSyncedProps() throws Exception {
        Connection conn = DriverManager.getConnection(getUrl(), new Properties());
        String tableName = createBaseTableWithProps(conn);

        // Test that we are not allowed to set any property to be kept in sync, specific to the new column family to be added
        for (String propName: SYNCED_DATA_TABLE_AND_INDEX_COL_FAM_PROPERTIES) {
            try {
                conn.createStatement().execute(
                        "alter table " + tableName + " add " + NEW_CF + ".new_column varchar(2) "
                                + NEW_CF + "." + propName + "=" + DUMMY_PROP_VALUE);
                fail("Should fail with SQLException when altering synced property for a"
                        + " specific column family when adding a column");
            } catch (SQLException sqlE) {
                assertEquals("Should fail to alter synced property for a specific"
                                + " column family when adding a column",
                        SQLExceptionCode.COLUMN_FAMILY_NOT_ALLOWED_FOR_PROPERTY.getErrorCode(),
                        sqlE.getErrorCode());
            }
        }

        // Test that when we add a new column (belonging to a new column family) and set any
        // property that should be in sync, then the property is modified for all existing
        // column families of the base table and its indexes
        Set<String> tablesToCheck = new HashSet<>();
        tablesToCheck.add(tableName);
        for (int i=0; i<2; i++) {
            tablesToCheck.add(createIndexTable(conn, tableName, PTable.IndexType.LOCAL).getSecond());
            tablesToCheck.add(createIndexTable(conn, tableName, PTable.IndexType.GLOBAL).getSecond());
        }
        // Create a view and view index
        tablesToCheck.add(createIndexTable(conn, tableName, null).getSecond());

        // Now add a new column family while simultaneously modifying properties to be kept in sync,
        // as well as a property which does not need to be kept in sync. Properties to be kept
        // in sync should get propagated to all index tables and already existing column families
        conn.createStatement().execute(
                "alter table " + tableName + " add " + NEW_CF + ".new_column varchar(2) "
                + "KEEP_DELETED_CELLS=" + MODIFIED_KEEP_DELETED_CELLS_VALUE
                + ",REPLICATION_SCOPE=" + MODIFIED_REPLICATION_SCOPE_VALUE
                + ",BLOCKSIZE=300000");

        for (String table: tablesToCheck) {
            verifyHBaseColumnFamilyProperties(table, conn, true, true);
        }
        try (Admin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
            HColumnDescriptor[] columnFamilies =
                    admin.getTableDescriptor(TableName.valueOf(tableName)).getColumnFamilies();
            for (HColumnDescriptor cfd: columnFamilies) {
                if (cfd.getNameAsString().equals(NEW_CF)) {
                    assertEquals("Newly added column fmaily should have updated property",
                            300000, cfd.getBlocksize());
                } else {
                    assertEquals("Existing column families should have default value for property",
                            HColumnDescriptor.DEFAULT_BLOCKSIZE, cfd.getBlocksize());
                }
            }
        }
        conn.close();
    }

    // Test that we disallow altering a synced property for a global index table
    @Test
    public void testDisallowAlterGlobalIndexTable() throws Exception {
        Connection conn = DriverManager.getConnection(getUrl(), new Properties());
        String tableName = createBaseTableWithProps(conn);
        String globalIndexName = createIndexTable(conn, tableName, PTable.IndexType.GLOBAL).getSecond();
        for (String propName: SYNCED_DATA_TABLE_AND_INDEX_COL_FAM_PROPERTIES) {
            try {
                conn.createStatement().execute("alter table " + globalIndexName + " set "
                + propName + "=" + DUMMY_PROP_VALUE);
                fail("Should fail with SQLException when altering synced property"
                        + " for a global index");
            } catch (SQLException sqlE) {
                assertEquals("Should fail to alter synced property for a global index",
                        SQLExceptionCode.CANNOT_SET_OR_ALTER_PROPERTY_FOR_INDEX.getErrorCode(),
                        sqlE.getErrorCode());
            }
        }
        conn.close();
    }

    // Test the upgrade code path for old client to new phoenix server cases in which the client
    // may have tables which have column families and indexes whose properties are out of sync
    @Test
    public void testOldClientSyncPropsUpgradePath() throws Exception {
        Connection conn = DriverManager.getConnection(getUrl(), new Properties());

        String baseTableName = createBaseTableWithProps(conn);
        String baseTableName1 = createBaseTableWithProps(conn);
        Set<String> createdTables = new HashSet<>();
        createdTables.add(baseTableName);
        createdTables.add(baseTableName1);
        // Create different indexes on the base table
        for (int i=0; i<2; i++) {
            createdTables.add(createIndexTable(conn, baseTableName, PTable.IndexType.GLOBAL).getSecond());
            createdTables.add(createIndexTable(conn, baseTableName, PTable.IndexType.LOCAL).getSecond());
            createdTables.add(createIndexTable(conn, baseTableName, null).getSecond());
            createdTables.add(createIndexTable(conn, baseTableName1, PTable.IndexType.GLOBAL).getSecond());
            createdTables.add(createIndexTable(conn, baseTableName1, PTable.IndexType.LOCAL).getSecond());
            createdTables.add(createIndexTable(conn, baseTableName1, null).getSecond());
        }
        for (String t: createdTables) {
            verifyHBaseColumnFamilyProperties(t, conn, false, false);
        }

        try (Admin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
            for (String tableName: createdTables) {
                final HTableDescriptor tableDescriptor;
                final HColumnDescriptor defaultCF;
                if (MetaDataUtil.isViewIndex(tableName)) {
                    // We won't be able to get the PTable for a view index table
                    tableDescriptor = conn.unwrap(PhoenixConnection.class).getQueryServices()
                            .getTableDescriptor(Bytes.toBytes(tableName));
                    defaultCF = tableDescriptor.getFamily(DEFAULT_COLUMN_FAMILY_BYTES);
                } else {
                    PTable table = PhoenixRuntime.getTable(conn, tableName);
                    tableDescriptor = conn.unwrap(PhoenixConnection.class).getQueryServices()
                            .getTableDescriptor(table.getPhysicalName().getBytes());
                    defaultCF = tableDescriptor.getFamily(SchemaUtil.getEmptyColumnFamily(table));
                }

                HTableDescriptor newTableDesc = new HTableDescriptor(tableDescriptor);
                if (tableName.equals(baseTableName) || tableName.equals(baseTableName1)) {
                    for (HColumnDescriptor cfd: tableDescriptor.getColumnFamilies()) {
                        // Modify all column families except the default column family
                        // for the base tables
                        if (!cfd.equals(defaultCF)) {
                            HColumnDescriptor newCfd = new HColumnDescriptor(cfd);
                            modifySyncedPropsForCF(newCfd);
                            newTableDesc.modifyFamily(newCfd);
                        }
                    }
                } else {
                    for (HColumnDescriptor cfd: tableDescriptor.getColumnFamilies()) {
                        // Modify all column families for other tables
                        HColumnDescriptor newCfd = new HColumnDescriptor(cfd);
                        modifySyncedPropsForCF(newCfd);
                        newTableDesc.modifyFamily(newCfd);
                    }
                }
                admin.modifyTable(newTableDesc.getTableName(), newTableDesc);
            }
        }
        // Now synchronize required properties and verify HBase metadata property values
        PhoenixConnection upgradeConn = conn.unwrap(PhoenixConnection.class);
        // Simulate an upgrade by setting the upgrade flag
        upgradeConn.setRunningUpgrade(true);
        syncTableAndIndexProperties(upgradeConn, upgradeConn.getQueryServices().getAdmin());
        for (String t: createdTables) {
            verifyHBaseColumnFamilyProperties(t, conn, false, false);
        }
        conn.close();
    }

    @Test
    public void testOldClientSyncUpdateCacheFreqUpgradePath() throws Exception {
        PTable base, index;
        String baseTableName, viewName, viewName2;
        Map<String, Set<String>> createdTablesAndViews = new HashMap<>();

        try (Connection conn = DriverManager.getConnection(getUrl(), new Properties())) {
            baseTableName = createBaseTableWithProps(conn);
            createdTablesAndViews.put(baseTableName, new HashSet<String>());
            Set<String> indexes = createdTablesAndViews.get(baseTableName);
            indexes.add(createIndexTable(conn, baseTableName, PTable.IndexType.GLOBAL).getSecond());
            indexes.add(createIndexTable(conn, baseTableName, PTable.IndexType.LOCAL).getFirst());

            viewName = createViewOnBaseTableOrView(conn, baseTableName);
            createdTablesAndViews.put(viewName, new HashSet<String>());
            indexes = createdTablesAndViews.get(viewName);
            indexes.add(createIndexTable(conn, viewName, PTable.IndexType.GLOBAL).getSecond());

            viewName2 = createViewOnBaseTableOrView(conn, viewName);
            createdTablesAndViews.put(viewName2, new HashSet<String>());
            indexes = createdTablesAndViews.get(viewName2);
            indexes.add(createIndexTable(conn, viewName2, PTable.IndexType.LOCAL).getFirst());

            // Intentionally make UPDATE_CACHE_FREQUENCY out of sync for indexes
            PreparedStatement stmt = conn.prepareStatement(UPSERT_UPDATE_CACHE_FREQUENCY);
            for (String tableOrViewName : createdTablesAndViews.keySet()) {
                base = PhoenixRuntime.getTable(conn, tableOrViewName);
                for (String indexTableName : createdTablesAndViews.get(tableOrViewName)) {
                    index = PhoenixRuntime.getTable(conn, indexTableName);
                    PName tenantId = index.getTenantId();
                    stmt.setString(1, tenantId == null ? null : tenantId.getString());
                    stmt.setString(2, index.getSchemaName().getString());
                    stmt.setString(3, index.getTableName().getString());
                    stmt.setLong(4, base.getType() == PTableType.TABLE ?
                            MODIFIED_UPDATE_CACHE_FREQUENCY : MODIFIED_UPDATE_CACHE_FREQUENCY_VIEWS);
                    stmt.addBatch();
                }
            }
            stmt.executeBatch();
            conn.commit();

            // Clear the server-side cache so that we get the latest built PTables
            conn.unwrap(PhoenixConnection.class).getQueryServices().clearCache();
            // Verify that the modified values are reflected
            for (String tableOrViewName : createdTablesAndViews.keySet()) {
                assertUpdateCacheFreq(conn, tableOrViewName, baseTableName.equals(tableOrViewName) ?
                        INITIAL_UPDATE_CACHE_FREQUENCY : INITIAL_UPDATE_CACHE_FREQUENCY_VIEWS);
                for (String indexName : createdTablesAndViews.get(tableOrViewName)) {
                    assertUpdateCacheFreq(conn, indexName, baseTableName.equals(tableOrViewName) ?
                            MODIFIED_UPDATE_CACHE_FREQUENCY : MODIFIED_UPDATE_CACHE_FREQUENCY_VIEWS);
                }
            }

            PhoenixConnection upgradeConn = conn.unwrap(PhoenixConnection.class);
            upgradeConn.setRunningUpgrade(true);
            syncUpdateCacheFreqAllIndexes(upgradeConn,
                    PhoenixRuntime.getTableNoCache(conn, baseTableName));

            conn.unwrap(PhoenixConnection.class).getQueryServices().clearCache();
            // Verify that indexes have the synced values for UPDATE_CACHE_FREQUENCY
            for (String tableOrViewName : createdTablesAndViews.keySet()) {
                long expectedVal = baseTableName.equals(tableOrViewName) ?
                        INITIAL_UPDATE_CACHE_FREQUENCY : INITIAL_UPDATE_CACHE_FREQUENCY_VIEWS;
                assertUpdateCacheFreq(conn, tableOrViewName, expectedVal);
                for (String indexOnTableOrView : createdTablesAndViews.get(tableOrViewName)) {
                    assertUpdateCacheFreq(conn, indexOnTableOrView, expectedVal);
                }
            }
        }
    }

    /**
     * Helper method to modify the synced properties for a column family descriptor
     * @param cfd The column family descriptor object
     * @throws SQLException
     */
    private void modifySyncedPropsForCF(HColumnDescriptor cfd) throws SQLException {
        cfd.setTimeToLive(MODIFIED_TTL_VALUE);
        cfd.setKeepDeletedCells(MODIFIED_KEEP_DELETED_CELLS_VALUE);
        cfd.setScope(MODIFIED_REPLICATION_SCOPE_VALUE);
    }

    /**
     * Helper method to create or alter a base table with specific values set for properties to be
     * kept in sync
     * @param conn Phoenix connection
     * @return Name of the HBase table created
     * @throws SQLException
     */
    private String createBaseTableWithProps(Connection conn) throws SQLException {
        String tableName = generateUniqueName();
        conn.createStatement().execute("create table " + tableName
                + " (id INTEGER not null primary key, type varchar(5), "
                + COL_FAM1 + ".name varchar(10), " + COL_FAM2 + ".flag boolean) "
                + "TTL=" + INITIAL_TTL_VALUE + ",KEEP_DELETED_CELLS=" + INITIAL_KEEP_DELETED_CELLS_VALUE
                + ",REPLICATION_SCOPE=" + INITIAL_REPLICATION_SCOPE_VALUE
                + ",UPDATE_CACHE_FREQUENCY=" + INITIAL_UPDATE_CACHE_FREQUENCY);
        return tableName;
    }

    /**
     * Helper method to create an index table on a base table.
     * @param conn Phoenix connection
     * @param baseTableName Name of the HBase base table on which to create an index
     * @param indexType LOCAL, GLOBAL or if we pass in null as the indexType,
     *                 we create a view and an index on that view for the given base table
     * @return A pair consisting of the index name and the name of the physical HBase table
     * corresponding to the index created
     * @throws SQLException
     */
    private Pair<String,String> createIndexTable(Connection conn, String baseTableName,
            PTable.IndexType indexType) throws SQLException {
        // Create a view on top of the base table and then an index on that view
        if (indexType == null) {
            String viewName = createViewOnBaseTableOrView(conn, baseTableName);
            String viewIndexName = VIEW_INDEX_TABLE_PREFIX + baseTableName;
            conn.createStatement().execute("create index view_index_" + generateUniqueName()
                    + " on " + viewName + " (flag)");
            return new Pair<>(viewIndexName, viewIndexName);
        }
        switch(indexType) {
        case LOCAL:
            String localIndexName = baseTableName + "_LOCAL_" + generateUniqueName();
            conn.createStatement().execute(
                    "create local index " + localIndexName + " on " + baseTableName + "(flag)");
            return new Pair<>(localIndexName, baseTableName);
        case GLOBAL:
            String globalIndexName = baseTableName + "_GLOBAL_" + generateUniqueName();
            conn.createStatement()
                    .execute("create index " + globalIndexName + " on " + baseTableName + "(name)");
            return new Pair<>(globalIndexName, globalIndexName);
        default:
            return new Pair<>(baseTableName, baseTableName);
        }
    }

    private String createViewOnBaseTableOrView(Connection conn, String baseTableOrView) throws SQLException {
        String viewName = "VIEW_" + baseTableOrView + "_" + generateUniqueName();
        conn.createStatement().execute("create view " + viewName
                + " (" + generateUniqueName() + " SMALLINT) as select * from "
                + baseTableOrView + " where id > 1 UPDATE_CACHE_FREQUENCY="
                + INITIAL_UPDATE_CACHE_FREQUENCY_VIEWS);
        return viewName;
    }

    /**
     * Helper method to verify HBase column family properties
     * @param tableName Physical HBase table whose properties are to be verified
     * @param conn Phoenix connection
     * @param propModified true if we have altered any of the properties to be kept in sync, false otherwise
     * @param ignoreTTL We cannot modfiy a table level property when adding a column, so in those cases,
     *                 ignore the check for TTL modification
     * @throws Exception
     */
    private void verifyHBaseColumnFamilyProperties(String tableName, Connection conn, boolean propModified,
            boolean ignoreTTL) throws Exception {
        final int expectedTTL = propModified ? MODIFIED_TTL_VALUE:INITIAL_TTL_VALUE;
        final KeepDeletedCells expectedKeepDeletedCells = propModified ?
                MODIFIED_KEEP_DELETED_CELLS_VALUE: INITIAL_KEEP_DELETED_CELLS_VALUE;
        final int expectedReplicationScope = propModified ?
                MODIFIED_REPLICATION_SCOPE_VALUE:INITIAL_REPLICATION_SCOPE_VALUE;

        try (Admin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
            // Note that this includes the local index column family as well
            HColumnDescriptor[] columnFamilies =
                    admin.getTableDescriptor(TableName.valueOf(tableName)).getColumnFamilies();
            for (HColumnDescriptor cfd: columnFamilies) {
                if (!ignoreTTL) {
                    assertEquals("Mismatch in TTL", expectedTTL, cfd.getTimeToLive());
                }
                assertEquals("Mismatch in KEEP_DELETED_CELLS", expectedKeepDeletedCells,
                        cfd.getKeepDeletedCells());
                assertEquals("Mismatch in REPLICATION_SCOPE", expectedReplicationScope,
                        cfd.getScope());
            }
        }
    }
}
