You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by td...@apache.org on 2018/11/06 23:19:27 UTC

[1/2] phoenix git commit: PHOENIX-4996: Refactor PTableImpl to use Builder Pattern

Repository: phoenix
Updated Branches:
  refs/heads/4.x-HBase-1.2 c509d58f1 -> 02a6bbce5


http://git-wip-us.apache.org/repos/asf/phoenix/blob/02a6bbce/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
index 9f06e04..7939b97 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
@@ -36,6 +36,7 @@ import java.util.Map.Entry;
 
 import javax.annotation.Nonnull;
 
+import com.google.common.annotations.VisibleForTesting;
 import org.apache.hadoop.hbase.Cell;
 import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.client.Delete;
@@ -69,7 +70,6 @@ import org.apache.phoenix.schema.types.PChar;
 import org.apache.phoenix.schema.types.PDataType;
 import org.apache.phoenix.schema.types.PDouble;
 import org.apache.phoenix.schema.types.PFloat;
-import org.apache.phoenix.schema.types.PLong;
 import org.apache.phoenix.schema.types.PVarchar;
 import org.apache.phoenix.transaction.TransactionFactory;
 import org.apache.phoenix.util.ByteUtil;
@@ -102,164 +102,661 @@ import com.google.common.collect.Maps;
 public class PTableImpl implements PTable {
     private static final Integer NO_SALTING = -1;
 
-    private PTableKey key;
-    private PName name;
-    private PName schemaName = PName.EMPTY_NAME;
-    private PName tableName = PName.EMPTY_NAME;
-    private PName tenantId;
-    private PTableType type;
-    private PIndexState state;
-    private long sequenceNumber;
-    private long timeStamp;
-    private long indexDisableTimestamp;
+    private IndexMaintainer indexMaintainer;
+    private ImmutableBytesWritable indexMaintainersPtr;
+
+    private final PTableKey key;
+    private final PName name;
+    private final PName schemaName;
+    private final PName tableName;
+    private final PName tenantId;
+    private final PTableType type;
+    private final PIndexState state;
+    private final long sequenceNumber;
+    private final long timeStamp;
+    private final long indexDisableTimestamp;
     // Have MultiMap for String->PColumn (may need family qualifier)
-    private List<PColumn> pkColumns;
-    private List<PColumn> allColumns;
+    private final List<PColumn> pkColumns;
+    private final List<PColumn> allColumns;
     // columns that were inherited from a parent table but that were dropped in the view
-    private List<PColumn> excludedColumns;
-    private List<PColumnFamily> families;
-    private Map<byte[], PColumnFamily> familyByBytes;
-    private Map<String, PColumnFamily> familyByString;
-    private ListMultimap<String, PColumn> columnsByName;
-    private Map<KVColumnFamilyQualifier, PColumn> kvColumnsByQualifiers;
-    private PName pkName;
-    private Integer bucketNum;
-    private RowKeySchema rowKeySchema;
+    private final List<PColumn> excludedColumns;
+    private final List<PColumnFamily> families;
+    private final Map<byte[], PColumnFamily> familyByBytes;
+    private final Map<String, PColumnFamily> familyByString;
+    private final ListMultimap<String, PColumn> columnsByName;
+    private final Map<KVColumnFamilyQualifier, PColumn> kvColumnsByQualifiers;
+    private final PName pkName;
+    private final Integer bucketNum;
+    private final RowKeySchema rowKeySchema;
     // Indexes associated with this table.
-    private List<PTable> indexes;
+    private final List<PTable> indexes;
     // Data table name that the index is created on.
-    private PName parentName;
-    private PName parentSchemaName;
-    private PName parentTableName;
-    private List<PName> physicalNames;
-    private boolean isImmutableRows;
-    private IndexMaintainer indexMaintainer;
-    private ImmutableBytesWritable indexMaintainersPtr;
-    private PName defaultFamilyName;
-    private String viewStatement;
-    private boolean disableWAL;
-    private boolean multiTenant;
-    private boolean storeNulls;
-    private TransactionFactory.Provider transactionProvider;
-    private ViewType viewType;
-    private PDataType viewIndexType;
-    private Long viewIndexId;
-    private int estimatedSize;
-    private IndexType indexType;
-    private int baseColumnCount;
-    private boolean rowKeyOrderOptimizable; // TODO: remove when required that tables have been upgrade for PHOENIX-2067
-    private boolean hasColumnsRequiringUpgrade; // TODO: remove when required that tables have been upgrade for PHOENIX-2067
-    private int rowTimestampColPos;
-    private long updateCacheFrequency;
-    private boolean isNamespaceMapped;
-    private String autoPartitionSeqName;
-    private boolean isAppendOnlySchema;
-    private ImmutableStorageScheme immutableStorageScheme;
-    private QualifierEncodingScheme qualifierEncodingScheme;
-    private EncodedCQCounter encodedCQCounter;
-    private Boolean useStatsForParallelization;
-
-    public PTableImpl() {
-        this.indexes = Collections.emptyList();
-        this.physicalNames = Collections.emptyList();
-        this.rowKeySchema = RowKeySchema.EMPTY_SCHEMA;
-    }
-    
-    // Constructor used at table creation time
-    public PTableImpl(PName tenantId, String schemaName, String tableName, long timestamp, List<PColumnFamily> families, boolean isNamespaceMapped) {
-        Preconditions.checkArgument(tenantId==null || tenantId.getBytes().length > 0); // tenantId should be null or not empty
-        this.tenantId = tenantId;
-        this.name = PNameFactory.newName(SchemaUtil.getTableName(schemaName, tableName));
-        this.key = new PTableKey(tenantId, name.getString());
-        this.schemaName = PNameFactory.newName(schemaName);
-        this.tableName = PNameFactory.newName(tableName);
-        this.type = PTableType.VIEW;
-        this.viewType = ViewType.MAPPED;
-        this.timeStamp = timestamp;
-        this.pkColumns = this.allColumns = Collections.emptyList();
-        this.rowKeySchema = RowKeySchema.EMPTY_SCHEMA;
-        this.indexes = Collections.emptyList();
-        this.familyByBytes = Maps.newHashMapWithExpectedSize(families.size());
-        this.familyByString = Maps.newHashMapWithExpectedSize(families.size());
-        for (PColumnFamily family : families) {
-            familyByBytes.put(family.getName().getBytes(), family);
-            familyByString.put(family.getName().getString(), family);
-        }
-        this.families = families;
-        this.physicalNames = Collections.emptyList();
-        this.isNamespaceMapped = isNamespaceMapped;
-    }
-    
-    public PTableImpl(PName tenantId, String schemaName, String tableName, long timestamp, List<PColumnFamily> families, boolean isNamespaceMapped, ImmutableStorageScheme storageScheme, QualifierEncodingScheme encodingScheme, Boolean useStatsForParallelization) { // For base table of mapped VIEW
-        Preconditions.checkArgument(tenantId==null || tenantId.getBytes().length > 0); // tenantId should be null or not empty
-        this.tenantId = tenantId;
-        this.name = PNameFactory.newName(SchemaUtil.getTableName(schemaName, tableName));
-        this.key = new PTableKey(tenantId, name.getString());
-        this.schemaName = PNameFactory.newName(schemaName);
-        this.tableName = PNameFactory.newName(tableName);
-        this.type = PTableType.VIEW;
-        this.viewType = ViewType.MAPPED;
-        this.timeStamp = timestamp;
-        this.pkColumns = this.allColumns = Collections.emptyList();
-        this.rowKeySchema = RowKeySchema.EMPTY_SCHEMA;
-        this.indexes = Collections.emptyList();
-        this.familyByBytes = Maps.newHashMapWithExpectedSize(families.size());
-        this.familyByString = Maps.newHashMapWithExpectedSize(families.size());
-        for (PColumnFamily family : families) {
-            familyByBytes.put(family.getName().getBytes(), family);
-            familyByString.put(family.getName().getString(), family);
-        }
-        this.families = families;
-        this.physicalNames = Collections.emptyList();
-        this.isNamespaceMapped = isNamespaceMapped;
-        this.immutableStorageScheme = storageScheme;
-        this.qualifierEncodingScheme = encodingScheme;
-        this.useStatsForParallelization = useStatsForParallelization;
-    }
-    
-    // For indexes stored in shared physical tables
-    public PTableImpl(PName tenantId, PName schemaName, PName tableName, long timestamp, List<PColumnFamily> families, 
-            List<PColumn> columns, List<PName> physicalNames, PDataType viewIndexType, Long viewIndexId, boolean multiTenant, boolean isNamespaceMpped, ImmutableStorageScheme storageScheme, QualifierEncodingScheme qualifierEncodingScheme,
-            EncodedCQCounter encodedCQCounter, Boolean useStatsForParallelization, Integer bucketNum) throws SQLException {
-        this.pkColumns = this.allColumns = Collections.emptyList();
-        this.rowKeySchema = RowKeySchema.EMPTY_SCHEMA;
-        this.indexes = Collections.emptyList();
-        this.familyByBytes = Maps.newHashMapWithExpectedSize(families.size());
-        this.familyByString = Maps.newHashMapWithExpectedSize(families.size());
-        for (PColumnFamily family : families) {
-            familyByBytes.put(family.getName().getBytes(), family);
-            familyByString.put(family.getName().getString(), family);
-        }
-        this.families = families;
-        if (bucketNum!=null) {
-            columns = columns.subList(1, columns.size());
-        }
-        init(tenantId, this.schemaName, this.tableName, PTableType.INDEX, state, timeStamp, sequenceNumber, pkName, bucketNum, columns,
-            this.schemaName, parentTableName, indexes, isImmutableRows, physicalNames, defaultFamilyName,
-            null, disableWAL, multiTenant, storeNulls, viewType, viewIndexType, viewIndexId, indexType, baseColumnCount, rowKeyOrderOptimizable,
-            transactionProvider, updateCacheFrequency, indexDisableTimestamp, isNamespaceMpped, null,
-            false, storageScheme, qualifierEncodingScheme, encodedCQCounter, useStatsForParallelization, null);
-    }
-
-    public PTableImpl(long timeStamp) { // For delete marker
-        this(timeStamp, false);
-    }
-
-    public PTableImpl(long timeStamp, boolean isIndex) { // For index delete marker
-        if (isIndex) {
-            this.type = PTableType.INDEX;
-            this.state = PIndexState.INACTIVE;
-        } else {
-            this.type = PTableType.TABLE;
+    private final PName parentName;
+    private final PName parentSchemaName;
+    private final PName parentTableName;
+    private final List<PName> physicalNames;
+    private final boolean isImmutableRows;
+    private final PName defaultFamilyName;
+    private final String viewStatement;
+    private final boolean disableWAL;
+    private final boolean multiTenant;
+    private final boolean storeNulls;
+    private final TransactionFactory.Provider transactionProvider;
+    private final ViewType viewType;
+    private final PDataType viewIndexType;
+    private final Long viewIndexId;
+    private final int estimatedSize;
+    private final IndexType indexType;
+    private final int baseColumnCount;
+    private final boolean rowKeyOrderOptimizable; // TODO: remove when required that tables have been upgrade for PHOENIX-2067
+    private final boolean hasColumnsRequiringUpgrade; // TODO: remove when required that tables have been upgrade for PHOENIX-2067
+    private final int rowTimestampColPos;
+    private final long updateCacheFrequency;
+    private final boolean isNamespaceMapped;
+    private final String autoPartitionSeqName;
+    private final boolean isAppendOnlySchema;
+    private final ImmutableStorageScheme immutableStorageScheme;
+    private final QualifierEncodingScheme qualifierEncodingScheme;
+    private final EncodedCQCounter encodedCQCounter;
+    private final Boolean useStatsForParallelization;
+
+    public static class Builder {
+        private PTableKey key;
+        private PName name;
+        private PName schemaName = PName.EMPTY_NAME;
+        private PName tableName = PName.EMPTY_NAME;
+        private PName tenantId;
+        private PTableType type;
+        private PIndexState state;
+        private long sequenceNumber;
+        private long timeStamp;
+        private long indexDisableTimestamp;
+        private List<PColumn> pkColumns;
+        private List<PColumn> allColumns;
+        private List<PColumn> excludedColumns;
+        private List<PColumnFamily> families;
+        private Map<byte[], PColumnFamily> familyByBytes;
+        private Map<String, PColumnFamily> familyByString;
+        private ListMultimap<String, PColumn> columnsByName;
+        private Map<KVColumnFamilyQualifier, PColumn> kvColumnsByQualifiers;
+        private PName pkName;
+        private Integer bucketNum;
+        private RowKeySchema rowKeySchema;
+        private List<PTable> indexes;
+        private PName parentName;
+        private PName parentSchemaName;
+        private PName parentTableName;
+        private List<PName> physicalNames;
+        private boolean isImmutableRows;
+        private IndexMaintainer indexMaintainer;
+        private ImmutableBytesWritable indexMaintainersPtr;
+        private PName defaultFamilyName;
+        private String viewStatement;
+        private boolean disableWAL;
+        private boolean multiTenant;
+        private boolean storeNulls;
+        private TransactionFactory.Provider transactionProvider;
+        private ViewType viewType;
+        private PDataType viewIndexType;
+        private Long viewIndexId;
+        private int estimatedSize;
+        private IndexType indexType;
+        private int baseColumnCount;
+        private boolean rowKeyOrderOptimizable;
+        private boolean hasColumnsRequiringUpgrade;
+        private int rowTimestampColPos;
+        private long updateCacheFrequency;
+        private boolean isNamespaceMapped;
+        private String autoPartitionSeqName;
+        private boolean isAppendOnlySchema;
+        private ImmutableStorageScheme immutableStorageScheme;
+        private QualifierEncodingScheme qualifierEncodingScheme;
+        private EncodedCQCounter encodedCQCounter;
+        private Boolean useStatsForParallelization;
+        // Optionally set columns for the builder, but not for the actual PTable
+        private Collection<PColumn> columns;
+
+        public Builder setKey(PTableKey key) {
+            this.key = key;
+            return this;
+        }
+
+        public Builder setName(PName name) {
+            this.name = name;
+            return this;
+        }
+
+        public Builder setSchemaName(PName schemaName) {
+            this.schemaName = schemaName;
+            return this;
+        }
+
+        public Builder setTableName(PName tableName) {
+            this.tableName = tableName;
+            return this;
+        }
+
+        public Builder setTenantId(PName tenantId) {
+            this.tenantId = tenantId;
+            return this;
+        }
+
+        public Builder setType(PTableType type) {
+            this.type = type;
+            return this;
+        }
+
+        public Builder setState(PIndexState state) {
+            this.state = state;
+            return this;
+        }
+
+        public Builder setSequenceNumber(long sequenceNumber) {
+            this.sequenceNumber = sequenceNumber;
+            return this;
+        }
+
+        public Builder setTimeStamp(long timeStamp) {
+            this.timeStamp = timeStamp;
+            return this;
+        }
+
+        public Builder setIndexDisableTimestamp(long indexDisableTimestamp) {
+            this.indexDisableTimestamp = indexDisableTimestamp;
+            return this;
+        }
+
+        public Builder setPkColumns(List<PColumn> pkColumns) {
+            this.pkColumns = pkColumns;
+            return this;
+        }
+
+        public Builder setAllColumns(List<PColumn> allColumns) {
+            this.allColumns = allColumns;
+            return this;
+        }
+
+        public Builder setExcludedColumns(List<PColumn> excludedColumns) {
+            this.excludedColumns = excludedColumns;
+            return this;
+        }
+
+        public Builder setFamilyAttributes(List<PColumnFamily> families) {
+            this.familyByBytes = Maps.newHashMapWithExpectedSize(families.size());
+            this.familyByString = Maps.newHashMapWithExpectedSize(families.size());
+            for (PColumnFamily family : families) {
+                familyByBytes.put(family.getName().getBytes(), family);
+                familyByString.put(family.getName().getString(), family);
+            }
+            this.families = families;
+            return this;
+        }
+
+        public Builder setFamilies(List<PColumnFamily> families) {
+            this.families = families;
+            return this;
+        }
+
+        public Builder setFamilyByBytes(Map<byte[], PColumnFamily> familyByBytes) {
+            this.familyByBytes = familyByBytes;
+            return this;
+        }
+
+        public Builder setFamilyByString(Map<String, PColumnFamily> familyByString) {
+            this.familyByString = familyByString;
+            return this;
+        }
+
+        public Builder setColumnsByName(ListMultimap<String, PColumn> columnsByName) {
+            this.columnsByName = columnsByName;
+            return this;
+        }
+
+        public Builder setKvColumnsByQualifiers(Map<KVColumnFamilyQualifier, PColumn> kvColumnsByQualifiers) {
+            this.kvColumnsByQualifiers = kvColumnsByQualifiers;
+            return this;
+        }
+
+        public Builder setPkName(PName pkName) {
+            this.pkName = pkName;
+            return this;
+        }
+
+        public Builder setBucketNum(Integer bucketNum) {
+            this.bucketNum = bucketNum;
+            return this;
+        }
+
+        public Builder setRowKeySchema(RowKeySchema rowKeySchema) {
+            this.rowKeySchema = rowKeySchema;
+            return this;
+        }
+
+        public Builder setIndexes(List<PTable> indexes) {
+            this.indexes = indexes;
+            return this;
+        }
+
+        public Builder setParentName(PName parentName) {
+            this.parentName = parentName;
+            return this;
+        }
+
+        public Builder setParentSchemaName(PName parentSchemaName) {
+            this.parentSchemaName = parentSchemaName;
+            return this;
+        }
+
+        public Builder setParentTableName(PName parentTableName) {
+            this.parentTableName = parentTableName;
+            return this;
+        }
+
+        public Builder setPhysicalNames(List<PName> physicalNames) {
+            this.physicalNames = physicalNames;
+            return this;
+        }
+
+        public Builder setImmutableRows(boolean immutableRows) {
+            isImmutableRows = immutableRows;
+            return this;
+        }
+
+        public Builder setIndexMaintainer(IndexMaintainer indexMaintainer) {
+            this.indexMaintainer = indexMaintainer;
+            return this;
+        }
+
+        public Builder setIndexMaintainersPtr(ImmutableBytesWritable indexMaintainersPtr) {
+            this.indexMaintainersPtr = indexMaintainersPtr;
+            return this;
+        }
+
+        public Builder setDefaultFamilyName(PName defaultFamilyName) {
+            this.defaultFamilyName = defaultFamilyName;
+            return this;
+        }
+
+        public Builder setViewStatement(String viewStatement) {
+            this.viewStatement = viewStatement;
+            return this;
+        }
+
+        public Builder setDisableWAL(boolean disableWAL) {
+            this.disableWAL = disableWAL;
+            return this;
+        }
+
+        public Builder setMultiTenant(boolean multiTenant) {
+            this.multiTenant = multiTenant;
+            return this;
+        }
+
+        public Builder setStoreNulls(boolean storeNulls) {
+            this.storeNulls = storeNulls;
+            return this;
+        }
+
+        public Builder setTransactionProvider(TransactionFactory.Provider transactionProvider) {
+            this.transactionProvider = transactionProvider;
+            return this;
+        }
+
+        public Builder setViewType(ViewType viewType) {
+            this.viewType = viewType;
+            return this;
+        }
+
+        public Builder setViewIndexType(PDataType viewIndexType) {
+            this.viewIndexType = viewIndexType;
+            return this;
+        }
+
+        public Builder setViewIndexId(Long viewIndexId) {
+            this.viewIndexId = viewIndexId;
+            return this;
+        }
+
+        public Builder setEstimatedSize(int estimatedSize) {
+            this.estimatedSize = estimatedSize;
+            return this;
+        }
+
+        public Builder setIndexType(IndexType indexType) {
+            this.indexType = indexType;
+            return this;
+        }
+
+        public Builder setBaseColumnCount(int baseColumnCount) {
+            this.baseColumnCount = baseColumnCount;
+            return this;
+        }
+
+        public Builder setRowKeyOrderOptimizable(boolean rowKeyOrderOptimizable) {
+            this.rowKeyOrderOptimizable = rowKeyOrderOptimizable;
+            return this;
+        }
+
+        public Builder setHasColumnsRequiringUpgrade(boolean hasColumnsRequiringUpgrade) {
+            this.hasColumnsRequiringUpgrade = hasColumnsRequiringUpgrade;
+            return this;
+        }
+
+        public Builder setRowTimestampColPos(int rowTimestampColPos) {
+            this.rowTimestampColPos = rowTimestampColPos;
+            return this;
+        }
+
+        public Builder setUpdateCacheFrequency(long updateCacheFrequency) {
+            this.updateCacheFrequency = updateCacheFrequency;
+            return this;
+        }
+
+        public Builder setNamespaceMapped(boolean namespaceMapped) {
+            isNamespaceMapped = namespaceMapped;
+            return this;
+        }
+
+        public Builder setAutoPartitionSeqName(String autoPartitionSeqName) {
+            this.autoPartitionSeqName = autoPartitionSeqName;
+            return this;
+        }
+
+        public Builder setAppendOnlySchema(boolean appendOnlySchema) {
+            isAppendOnlySchema = appendOnlySchema;
+            return this;
+        }
+
+        public Builder setImmutableStorageScheme(ImmutableStorageScheme immutableStorageScheme) {
+            this.immutableStorageScheme = immutableStorageScheme;
+            return this;
+        }
+
+        public Builder setQualifierEncodingScheme(QualifierEncodingScheme qualifierEncodingScheme) {
+            this.qualifierEncodingScheme = qualifierEncodingScheme;
+            return this;
+        }
+
+        public Builder setEncodedCQCounter(EncodedCQCounter encodedCQCounter) {
+            this.encodedCQCounter = encodedCQCounter;
+            return this;
+        }
+
+        public Builder setUseStatsForParallelization(Boolean useStatsForParallelization) {
+            this.useStatsForParallelization = useStatsForParallelization;
+            return this;
+        }
+
+        /**
+         * Note: When set in the builder, we must call {@link Builder#initDerivedAttributes()}
+         * before building the PTable in order to correctly populate other attributes of the PTable
+         * @param columns PColumns to be set in the builder
+         * @return PTableImpl.Builder object
+         */
+        public Builder setColumns(Collection<PColumn> columns) {
+            this.columns = columns;
+            return this;
+        }
+
+        /**
+         * Populate derivable attributes of the PTable
+         * @return PTableImpl.Builder object
+         * @throws SQLException
+         */
+        private Builder initDerivedAttributes() throws SQLException {
+            checkTenantId(this.tenantId);
+            Preconditions.checkNotNull(this.schemaName);
+            Preconditions.checkNotNull(this.tableName);
+            Preconditions.checkNotNull(this.columns);
+            Preconditions.checkNotNull(this.indexes);
+            Preconditions.checkNotNull(this.physicalNames);
+            Preconditions.checkNotNull(this.hasColumnsRequiringUpgrade);
+            Preconditions.checkNotNull(this.rowKeyOrderOptimizable);
+
+            PName fullName = PNameFactory.newName(SchemaUtil.getTableName(
+                    this.schemaName.getString(), this.tableName.getString()));
+            int estimatedSize = SizedUtil.OBJECT_SIZE * 2 + 23 * SizedUtil.POINTER_SIZE +
+                    4 * SizedUtil.INT_SIZE + 2 * SizedUtil.LONG_SIZE + 2 * SizedUtil.INT_OBJECT_SIZE +
+                    PNameFactory.getEstimatedSize(this.tenantId) +
+                    PNameFactory.getEstimatedSize(this.schemaName) +
+                    PNameFactory.getEstimatedSize(this.tableName) +
+                    PNameFactory.getEstimatedSize(this.pkName) +
+                    PNameFactory.getEstimatedSize(this.parentTableName) +
+                    PNameFactory.getEstimatedSize(this.defaultFamilyName);
+            int numPKColumns = 0;
+            List<PColumn> pkColumns;
+            PColumn[] allColumns;
+            if (this.bucketNum != null) {
+                // Add salt column to allColumns and pkColumns, but don't add to
+                // columnsByName, since it should not be addressable via name.
+                allColumns = new PColumn[this.columns.size()+1];
+                allColumns[SALTING_COLUMN.getPosition()] = SALTING_COLUMN;
+                pkColumns = Lists.newArrayListWithExpectedSize(this.columns.size()+1);
+                ++numPKColumns;
+            } else {
+                allColumns = new PColumn[this.columns.size()];
+                pkColumns = Lists.newArrayListWithExpectedSize(this.columns.size());
+            }
+            // Must do this as with the new method of storing diffs, we just care about
+            // ordinal position relative order and not the true ordinal value itself.
+            List<PColumn> sortedColumns = Lists.newArrayList(this.columns);
+            Collections.sort(sortedColumns, new Comparator<PColumn>() {
+                @Override
+                public int compare(PColumn o1, PColumn o2) {
+                    return Integer.valueOf(o1.getPosition()).compareTo(o2.getPosition());
+                }
+            });
+
+            int position = 0;
+            if (this.bucketNum != null) {
+                position = 1;
+            }
+            ListMultimap<String, PColumn> populateColumnsByName =
+                    ArrayListMultimap.create(this.columns.size(), 1);
+            Map<KVColumnFamilyQualifier, PColumn> populateKvColumnsByQualifiers =
+                    Maps.newHashMapWithExpectedSize(this.columns.size());
+            for (PColumn column : sortedColumns) {
+                allColumns[position] = column;
+                position++;
+                PName familyName = column.getFamilyName();
+                if (familyName == null) {
+                    ++numPKColumns;
+                }
+                String columnName = column.getName().getString();
+                if (populateColumnsByName.put(columnName, column)) {
+                    int count = 0;
+                    for (PColumn dupColumn : populateColumnsByName.get(columnName)) {
+                        if (Objects.equal(familyName, dupColumn.getFamilyName())) {
+                            count++;
+                            if (count > 1) {
+                                throw new ColumnAlreadyExistsException(this.schemaName.getString(),
+                                        fullName.getString(), columnName);
+                            }
+                        }
+                    }
+                }
+                byte[] cq = column.getColumnQualifierBytes();
+                String cf = column.getFamilyName() != null ?
+                        column.getFamilyName().getString() : null;
+                if (cf != null && cq != null) {
+                    KVColumnFamilyQualifier info = new KVColumnFamilyQualifier(cf, cq);
+                    if (populateKvColumnsByQualifiers.get(info) != null) {
+                        throw new ColumnAlreadyExistsException(this.schemaName.getString(),
+                                fullName.getString(), columnName);
+                    }
+                    populateKvColumnsByQualifiers.put(info, column);
+                }
+            }
+            estimatedSize += SizedUtil.sizeOfMap(allColumns.length, SizedUtil.POINTER_SIZE,
+                    SizedUtil.sizeOfArrayList(1)); // for multi-map
+            estimatedSize += SizedUtil.sizeOfMap(numPKColumns) +
+                    SizedUtil.sizeOfMap(allColumns.length);
+
+            RowKeySchemaBuilder builder = new RowKeySchemaBuilder(numPKColumns);
+            // Two pass so that column order in column families matches overall column order
+            // and to ensure that column family order is constant
+            int maxExpectedSize = allColumns.length - numPKColumns;
+            // Maintain iteration order so that column families are ordered as they are listed
+            Map<PName, List<PColumn>> familyMap = Maps.newLinkedHashMap();
+            PColumn rowTimestampCol = null;
+            boolean hasColsRequiringUpgrade = false;
+            for (PColumn column : allColumns) {
+                PName familyName = column.getFamilyName();
+                if (familyName == null) {
+                    hasColsRequiringUpgrade |=
+                            (column.getSortOrder() == SortOrder.DESC
+                                    && (!column.getDataType().isFixedWidth()
+                                    || column.getDataType() == PChar.INSTANCE
+                                    || column.getDataType() == PFloat.INSTANCE
+                                    || column.getDataType() == PDouble.INSTANCE
+                                    || column.getDataType() == PBinary.INSTANCE) )
+                                    || (column.getSortOrder() == SortOrder.ASC
+                                        && column.getDataType() == PBinary.INSTANCE
+                                        && column.getMaxLength() != null
+                                        && column.getMaxLength() > 1);
+                    pkColumns.add(column);
+                    if (column.isRowTimestamp()) {
+                        rowTimestampCol = column;
+                    }
+                }
+                if (familyName == null) {
+                    estimatedSize += column.getEstimatedSize(); // PK columns
+                    builder.addField(column, column.isNullable(), column.getSortOrder());
+                } else {
+                    List<PColumn> columnsInFamily = familyMap.get(familyName);
+                    if (columnsInFamily == null) {
+                        columnsInFamily = Lists.newArrayListWithExpectedSize(maxExpectedSize);
+                        familyMap.put(familyName, columnsInFamily);
+                    }
+                    columnsInFamily.add(column);
+                }
+            }
+            int rowTimestampColPos;
+            if (rowTimestampCol != null) {
+                rowTimestampColPos = pkColumns.indexOf(rowTimestampCol);
+            } else {
+                rowTimestampColPos = -1;
+            }
+
+            Iterator<Map.Entry<PName,List<PColumn>>> iterator = familyMap.entrySet().iterator();
+            PColumnFamily[] families = new PColumnFamily[familyMap.size()];
+            ImmutableMap.Builder<String, PColumnFamily> familyByString = ImmutableMap.builder();
+            ImmutableSortedMap.Builder<byte[], PColumnFamily> familyByBytes = ImmutableSortedMap
+                    .orderedBy(Bytes.BYTES_COMPARATOR);
+            for (int i = 0; i < families.length; i++) {
+                Map.Entry<PName,List<PColumn>> entry = iterator.next();
+                PColumnFamily family = new PColumnFamilyImpl(entry.getKey(), entry.getValue());
+                families[i] = family;
+                familyByString.put(family.getName().getString(), family);
+                familyByBytes.put(family.getName().getBytes(), family);
+                estimatedSize += family.getEstimatedSize();
+            }
+            estimatedSize += SizedUtil.sizeOfArrayList(families.length);
+            estimatedSize += SizedUtil.sizeOfMap(families.length) * 2;
+            for (PTable index : this.indexes) {
+                estimatedSize += index.getEstimatedSize();
+            }
+
+            estimatedSize += PNameFactory.getEstimatedSize(this.parentName);
+            for (PName physicalName : this.physicalNames) {
+                estimatedSize += physicalName.getEstimatedSize();
+            }
+            // Populate the derived fields and return the builder
+            return this.setName(fullName)
+                    .setKey(new PTableKey(this.tenantId, fullName.getString()))
+                    .setParentName(this.parentTableName == null ? null :
+                            PNameFactory.newName(SchemaUtil.getTableName(
+                                    this.parentSchemaName != null ?
+                                            this.parentSchemaName.getString() : null,
+                                    this.parentTableName.getString())))
+                    .setColumnsByName(populateColumnsByName)
+                    .setKvColumnsByQualifiers(populateKvColumnsByQualifiers)
+                    .setAllColumns(ImmutableList.copyOf(allColumns))
+                    .setHasColumnsRequiringUpgrade(hasColsRequiringUpgrade
+                            | this.hasColumnsRequiringUpgrade)
+                    .setPkColumns(ImmutableList.copyOf(pkColumns))
+                    .setRowTimestampColPos(rowTimestampColPos)
+                    // after hasDescVarLengthColumns is calculated
+                    .setRowKeySchema(builder.rowKeyOrderOptimizable(
+                            this.rowKeyOrderOptimizable || !this.hasColumnsRequiringUpgrade)
+                            .build())
+                    .setFamilies(ImmutableList.copyOf(families))
+                    .setFamilyByBytes(familyByBytes.build())
+                    .setFamilyByString(familyByString.build())
+                    .setEstimatedSize(estimatedSize + this.rowKeySchema.getEstimatedSize());
         }
-        this.timeStamp = timeStamp;
-        this.pkColumns = this.allColumns = Collections.emptyList();
-        this.families = Collections.emptyList();
-        this.familyByBytes = Collections.emptyMap();
-        this.familyByString = Collections.emptyMap();
-        this.rowKeySchema = RowKeySchema.EMPTY_SCHEMA;
-        this.indexes = Collections.emptyList();
-        this.physicalNames = Collections.emptyList();;
+
+        public PTableImpl build() throws SQLException {
+            // Note that we call initDerivedAttributes to populate derivable attributes if
+            // this.columns is set in the PTableImpl.Builder object
+            return (this.columns == null) ? new PTableImpl(this) :
+                    new PTableImpl(this.initDerivedAttributes());
+        }
+
+    }
+
+    @VisibleForTesting
+    PTableImpl() {
+        this(new PTableImpl.Builder()
+                .setIndexes(Collections.<PTable>emptyList())
+                .setPhysicalNames(Collections.<PName>emptyList())
+                .setRowKeySchema(RowKeySchema.EMPTY_SCHEMA));
+    }
+
+    // Private constructor used by the builder
+    private PTableImpl(Builder builder) {
+        this.key = builder.key;
+        this.name = builder.name;
+        this.schemaName = builder.schemaName;
+        this.tableName = builder.tableName;
+        this.tenantId = builder.tenantId;
+        this.type = builder.type;
+        this.state = builder.state;
+        this.sequenceNumber = builder.sequenceNumber;
+        this.timeStamp = builder.timeStamp;
+        this.indexDisableTimestamp = builder.indexDisableTimestamp;
+        this.pkColumns = builder.pkColumns;
+        this.allColumns = builder.allColumns;
+        this.excludedColumns = builder.excludedColumns;
+        this.families = builder.families;
+        this.familyByBytes = builder.familyByBytes;
+        this.familyByString = builder.familyByString;
+        this.columnsByName = builder.columnsByName;
+        this.kvColumnsByQualifiers = builder.kvColumnsByQualifiers;
+        this.pkName = builder.pkName;
+        this.bucketNum = builder.bucketNum;
+        this.rowKeySchema = builder.rowKeySchema;
+        this.indexes = builder.indexes;
+        this.parentName = builder.parentName;
+        this.parentSchemaName = builder.parentSchemaName;
+        this.parentTableName = builder.parentTableName;
+        this.physicalNames = builder.physicalNames;
+        this.isImmutableRows = builder.isImmutableRows;
+        this.indexMaintainer = builder.indexMaintainer;
+        this.indexMaintainersPtr = builder.indexMaintainersPtr;
+        this.defaultFamilyName = builder.defaultFamilyName;
+        this.viewStatement = builder.viewStatement;
+        this.disableWAL = builder.disableWAL;
+        this.multiTenant = builder.multiTenant;
+        this.storeNulls = builder.storeNulls;
+        this.transactionProvider = builder.transactionProvider;
+        this.viewType = builder.viewType;
+        this.viewIndexType = builder.viewIndexType;
+        this.viewIndexId = builder.viewIndexId;
+        this.estimatedSize = builder.estimatedSize;
+        this.indexType = builder.indexType;
+        this.baseColumnCount = builder.baseColumnCount;
+        this.rowKeyOrderOptimizable = builder.rowKeyOrderOptimizable;
+        this.hasColumnsRequiringUpgrade = builder.hasColumnsRequiringUpgrade;
+        this.rowTimestampColPos = builder.rowTimestampColPos;
+        this.updateCacheFrequency = builder.updateCacheFrequency;
+        this.isNamespaceMapped = builder.isNamespaceMapped;
+        this.autoPartitionSeqName = builder.autoPartitionSeqName;
+        this.isAppendOnlySchema = builder.isAppendOnlySchema;
+        this.immutableStorageScheme = builder.immutableStorageScheme;
+        this.qualifierEncodingScheme = builder.qualifierEncodingScheme;
+        this.encodedCQCounter = builder.encodedCQCounter;
+        this.useStatsForParallelization = builder.useStatsForParallelization;
     }
 
     // When cloning table, ignore the salt column as it will be added back in the constructor
@@ -267,153 +764,65 @@ public class PTableImpl implements PTable {
         return table.getBucketNum() == null ? table.getColumns() : table.getColumns().subList(1, table.getColumns().size());
     }
 
-    public static PTableImpl makePTable(PTable table, long timeStamp, List<PTable> indexes) throws SQLException {
-        return new PTableImpl(table, table.rowKeyOrderOptimizable(), table.getIndexState(), timeStamp,
-                table.getSequenceNumber(), getColumnsToClone(table), table.getDefaultFamilyName(), table.getType(),
-                table.getBaseColumnCount(), table.getSchemaName(), table.getTableName(), table.getViewStatement(),
-                table.getUpdateCacheFrequency(), table.getTenantId(), indexes);
-    }
-
-    public static PTable makePTable(PTable index, PName indexName, String viewStatement, long updateCacheFrequency,
-            PName tenantId) throws SQLException {
-        return Objects.equal(viewStatement, index.getViewStatement()) ? index
-                : new PTableImpl(index, index.rowKeyOrderOptimizable(), index.getIndexState(), index.getTimeStamp(),
-                        index.getSequenceNumber(), index.getColumns(), index.getDefaultFamilyName(), index.getType(),
-                        index.getBaseColumnCount(), index.getSchemaName(), indexName,
-                        viewStatement, updateCacheFrequency, tenantId,
-                        index.getIndexes());
-    }
-    
-    public static PTableImpl makePTable(PTable table, Collection<PColumn> columns) throws SQLException {
-        return new PTableImpl(table, table.rowKeyOrderOptimizable(), table.getIndexState(), table.getTimeStamp(),
-                table.getSequenceNumber(), columns, table.getDefaultFamilyName(), table.getType(),
-                table.getBaseColumnCount(), table.getSchemaName(), table.getTableName(), table.getViewStatement(),
-                table.getUpdateCacheFrequency(), table.getTenantId(), table.getIndexes());
+    /**
+     * Get a PTableImpl.Builder from an existing PTable and set the builder columns
+     * @param table Original PTable
+     * @param columns Columns to set in the builder for the new PTable to be constructed
+     * @return PTable builder object based on an existing PTable
+     */
+    public static PTableImpl.Builder builderWithColumns(PTable table, Collection<PColumn> columns) {
+        return builderFromExisting(table).setColumns(columns);
     }
 
     /**
-     * Used to create a PTable for views or view indexes, the basePTable is for attributes we inherit from the physical table
+     * Get a PTableImpl.Builder from an existing PTable
+     * @param table Original PTable
      */
-    public static PTableImpl makePTable(PTable view, PTable baseTable, Collection<PColumn> columns, long timestamp, int baseTableColumnCount, Collection<PColumn> excludedColumns) throws SQLException {
-        // if a TableProperty is not valid on a view we set it to the base table value
-        // if a TableProperty is valid on a view and is not mutable on a view we set it to the base table value
-        // if a TableProperty is valid on a view and is mutable on a view we use the value set on the view 
-        return new PTableImpl(
-            view.getTenantId(), view.getSchemaName(), view.getTableName(), view.getType(), view.getIndexState(), timestamp,
-            view.getSequenceNumber(), view.getPKName(), view.getBucketNum(), columns, view.getParentSchemaName(), view.getParentTableName(),
-            view.getIndexes(), baseTable.isImmutableRows(), view.getPhysicalNames(), view.getDefaultFamilyName(), view.getViewStatement(),
-            baseTable.isWALDisabled(), baseTable.isMultiTenant(), baseTable.getStoreNulls(), view.getViewType(),
-            view.getViewIndexType(), view.getViewIndexId(), view.getIndexType(),
-            baseTableColumnCount, view.rowKeyOrderOptimizable(), baseTable.getTransactionProvider(), view.getUpdateCacheFrequency(),
-            view.getIndexDisableTimestamp(), view.isNamespaceMapped(), baseTable.getAutoPartitionSeqName(), baseTable.isAppendOnlySchema(),
-            baseTable.getImmutableStorageScheme(), baseTable.getEncodingScheme(), view.getEncodedCQCounter(), view.useStatsForParallelization(), excludedColumns);
+    private static PTableImpl.Builder builderFromExisting(PTable table) {
+        return new PTableImpl.Builder()
+                .setType(table.getType())
+                .setState(table.getIndexState())
+                .setTimeStamp(table.getTimeStamp())
+                .setIndexDisableTimestamp(table.getIndexDisableTimestamp())
+                .setSequenceNumber(table.getSequenceNumber())
+                .setImmutableRows(table.isImmutableRows())
+                .setViewStatement(table.getViewStatement())
+                .setDisableWAL(table.isWALDisabled())
+                .setMultiTenant(table.isMultiTenant())
+                .setStoreNulls(table.getStoreNulls())
+                .setViewType(table.getViewType())
+                .setViewIndexType(table.getViewIndexType())
+                .setViewIndexId(table.getViewIndexId())
+                .setIndexType(table.getIndexType())
+                .setTransactionProvider(table.getTransactionProvider())
+                .setUpdateCacheFrequency(table.getUpdateCacheFrequency())
+                .setNamespaceMapped(table.isNamespaceMapped())
+                .setAutoPartitionSeqName(table.getAutoPartitionSeqName())
+                .setAppendOnlySchema(table.isAppendOnlySchema())
+                .setImmutableStorageScheme(table.getImmutableStorageScheme() == null ?
+                        ImmutableStorageScheme.ONE_CELL_PER_COLUMN : table.getImmutableStorageScheme())
+                .setQualifierEncodingScheme(table.getEncodingScheme() == null ?
+                        QualifierEncodingScheme.NON_ENCODED_QUALIFIERS : table.getEncodingScheme())
+                .setBaseColumnCount(table.getBaseColumnCount())
+                .setEncodedCQCounter(table.getEncodedCQCounter())
+                .setUseStatsForParallelization(table.useStatsForParallelization())
+                .setExcludedColumns(table.getExcludedColumns() == null ?
+                        ImmutableList.<PColumn>of() : ImmutableList.copyOf(table.getExcludedColumns()))
+                .setTenantId(table.getTenantId())
+                .setSchemaName(table.getSchemaName())
+                .setTableName(table.getTableName())
+                .setPkName(table.getPKName())
+                .setDefaultFamilyName(table.getDefaultFamilyName())
+                .setRowKeyOrderOptimizable(table.rowKeyOrderOptimizable())
+                .setBucketNum(table.getBucketNum())
+                .setIndexes(table.getIndexes() == null ?
+                        Collections.<PTable>emptyList() : table.getIndexes())
+                .setParentSchemaName(table.getParentSchemaName())
+                .setParentTableName(table.getParentTableName())
+                .setPhysicalNames(table.getPhysicalNames() == null ?
+                        ImmutableList.<PName>of() : ImmutableList.copyOf(table.getPhysicalNames()));
     }
-    
-    public static PTableImpl makePTable(PTable table, PTableType type, Collection<PColumn> columns) throws SQLException {
-        return new PTableImpl(table, table.rowKeyOrderOptimizable(), table.getIndexState(), table.getTimeStamp(),
-                table.getSequenceNumber(), columns, table.getDefaultFamilyName(), type,
-                table.getBaseColumnCount(), table.getSchemaName(), table.getTableName(), table.getViewStatement(),
-                table.getUpdateCacheFrequency(), table.getTenantId(), table.getIndexes());
-    }
-
-    public static PTableImpl makePTable(PTable table, Collection<PColumn> columns, PName defaultFamily)
-            throws SQLException {
-        return new PTableImpl(table, table.rowKeyOrderOptimizable(), table.getIndexState(), table.getTimeStamp(),
-                table.getSequenceNumber(), columns, defaultFamily, table.getType(),
-                table.getBaseColumnCount(), table.getSchemaName(), table.getTableName(), table.getViewStatement(),
-                table.getUpdateCacheFrequency(), table.getTenantId(), table.getIndexes());
-    }
-
-    public static PTableImpl makePTable(PTable table, long timeStamp, long sequenceNumber, Collection<PColumn> columns)
-            throws SQLException {
-        return new PTableImpl(table, table.rowKeyOrderOptimizable(), table.getIndexState(), timeStamp,
-                sequenceNumber, columns, table.getDefaultFamilyName(), table.getType(),
-                table.getBaseColumnCount(), table.getSchemaName(), table.getTableName(), table.getViewStatement(),
-                table.getUpdateCacheFrequency(), table.getTenantId(), table.getIndexes());
-    }
-
-    public static PTableImpl makePTable(PTable table, PIndexState state) throws SQLException {
-        return new PTableImpl(table, table.rowKeyOrderOptimizable(), state, table.getTimeStamp(),
-                table.getSequenceNumber(), getColumnsToClone(table), table.getDefaultFamilyName(), table.getType(),
-                table.getBaseColumnCount(), table.getSchemaName(), table.getTableName(), table.getViewStatement(),
-                table.getUpdateCacheFrequency(), table.getTenantId(), table.getIndexes());
-    }
-
-    public static PTableImpl makePTable(PTable table, boolean rowKeyOrderOptimizable) throws SQLException {
-        return new PTableImpl(table, rowKeyOrderOptimizable, table.getIndexState(), table.getTimeStamp(),
-                table.getSequenceNumber(), getColumnsToClone(table), table.getDefaultFamilyName(), table.getType(),
-                table.getBaseColumnCount(), table.getSchemaName(), table.getTableName(), table.getViewStatement(),
-                table.getUpdateCacheFrequency(), table.getTenantId(), table.getIndexes());
-    }
-
-    public static PTableImpl makePTable(PName tenantId, PName schemaName, PName tableName, PTableType type,
-            PIndexState state, long timeStamp, long sequenceNumber, PName pkName, Integer bucketNum,
-            Collection<PColumn> columns, PName dataSchemaName, PName dataTableName, List<PTable> indexes,
-            boolean isImmutableRows, List<PName> physicalNames, PName defaultFamilyName, String viewExpression,
-            boolean disableWAL, boolean multiTenant, boolean storeNulls, ViewType viewType, PDataType viewIndexType, Long viewIndexId,
-            IndexType indexType, boolean rowKeyOrderOptimizable, TransactionFactory.Provider transactionProvider,
-            long updateCacheFrequency, long indexDisableTimestamp, boolean isNamespaceMapped,
-            String autoPartitionSeqName, boolean isAppendOnlySchema, ImmutableStorageScheme storageScheme,
-            QualifierEncodingScheme qualifierEncodingScheme, EncodedCQCounter encodedCQCounter,
-            Boolean useStatsForParallelization) throws SQLException {
-        return new PTableImpl(tenantId, schemaName, tableName, type, state, timeStamp, sequenceNumber, pkName,
-                bucketNum, columns, dataSchemaName, dataTableName, indexes, isImmutableRows, physicalNames,
-                defaultFamilyName, viewExpression, disableWAL, multiTenant, storeNulls, viewType, viewIndexType, viewIndexId,
-                indexType, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, rowKeyOrderOptimizable, transactionProvider,
-                updateCacheFrequency, indexDisableTimestamp, isNamespaceMapped, autoPartitionSeqName,
-                isAppendOnlySchema, storageScheme, qualifierEncodingScheme, encodedCQCounter,
-                useStatsForParallelization, null);
-    }
-
-    public static PTableImpl makePTable(PName tenantId, PName schemaName, PName tableName, PTableType type,
-            PIndexState state, long timeStamp, long sequenceNumber, PName pkName, Integer bucketNum,
-            Collection<PColumn> columns, PName dataSchemaName, PName dataTableName, List<PTable> indexes,
-            boolean isImmutableRows, List<PName> physicalNames, PName defaultFamilyName, String viewExpression,
-            boolean disableWAL, boolean multiTenant, boolean storeNulls, ViewType viewType, PDataType viewIndexType, Long viewIndexId,
-            IndexType indexType, boolean rowKeyOrderOptimizable, TransactionFactory.Provider transactionProvider,
-            long updateCacheFrequency, int baseColumnCount, long indexDisableTimestamp, boolean isNamespaceMapped,
-            String autoPartitionSeqName, boolean isAppendOnlySchema, ImmutableStorageScheme storageScheme,
-            QualifierEncodingScheme qualifierEncodingScheme, EncodedCQCounter encodedCQCounter,
-            Boolean useStatsForParallelization) throws SQLException {
-        return new PTableImpl(tenantId, schemaName, tableName, type, state, timeStamp, sequenceNumber, pkName,
-                bucketNum, columns, dataSchemaName, dataTableName, indexes, isImmutableRows, physicalNames,
-                defaultFamilyName, viewExpression, disableWAL, multiTenant, storeNulls, viewType,viewIndexType,  viewIndexId,
-                indexType, baseColumnCount, rowKeyOrderOptimizable, transactionProvider, updateCacheFrequency,
-                indexDisableTimestamp, isNamespaceMapped, autoPartitionSeqName, isAppendOnlySchema, storageScheme,
-                qualifierEncodingScheme, encodedCQCounter, useStatsForParallelization, null);
-    }
-
-    private PTableImpl(PTable table, boolean rowKeyOrderOptimizable, PIndexState state, long timeStamp,
-            long sequenceNumber, Collection<PColumn> columns, PName defaultFamily, PTableType type,
-            int baseTableColumnCount, PName schemaName, PName tableName, String viewStatement,
-            long updateCacheFrequency, PName tenantId, List<PTable> indexes) throws SQLException {
-        init(tenantId, schemaName, tableName, type, state, timeStamp, sequenceNumber, table.getPKName(),
-                table.getBucketNum(), columns, table.getParentSchemaName(), table.getParentTableName(), indexes,
-                table.isImmutableRows(), table.getPhysicalNames(), defaultFamily, viewStatement, table.isWALDisabled(),
-                table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexType(), table.getViewIndexId(),
-                table.getIndexType(), baseTableColumnCount, rowKeyOrderOptimizable, table.getTransactionProvider(),
-                updateCacheFrequency, table.getIndexDisableTimestamp(), table.isNamespaceMapped(),
-                table.getAutoPartitionSeqName(), table.isAppendOnlySchema(), table.getImmutableStorageScheme(),
-                table.getEncodingScheme(), table.getEncodedCQCounter(), table.useStatsForParallelization(), null);
-    }
-
-    private PTableImpl(PName tenantId, PName schemaName, PName tableName, PTableType type, PIndexState state,
-            long timeStamp, long sequenceNumber, PName pkName, Integer bucketNum, Collection<PColumn> columns,
-            PName parentSchemaName, PName parentTableName, List<PTable> indexes, boolean isImmutableRows,
-            List<PName> physicalNames, PName defaultFamilyName, String viewExpression, boolean disableWAL, boolean multiTenant,
-            boolean storeNulls, ViewType viewType, PDataType viewIndexType, Long viewIndexId, IndexType indexType,
-            int baseColumnCount, boolean rowKeyOrderOptimizable, TransactionFactory.Provider transactionProvider, long updateCacheFrequency,
-            long indexDisableTimestamp, boolean isNamespaceMapped, String autoPartitionSeqName, boolean isAppendOnlySchema, ImmutableStorageScheme storageScheme, 
-            QualifierEncodingScheme qualifierEncodingScheme, EncodedCQCounter encodedCQCounter,
-            Boolean useStatsForParallelization, Collection<PColumn> excludedColumns)
-            throws SQLException {
-        init(tenantId, schemaName, tableName, type, state, timeStamp, sequenceNumber, pkName, bucketNum, columns,
-                parentSchemaName, parentTableName, indexes, isImmutableRows, physicalNames, defaultFamilyName,
-                viewExpression, disableWAL, multiTenant, storeNulls, viewType, viewIndexType, viewIndexId, indexType, baseColumnCount, rowKeyOrderOptimizable,
-                transactionProvider, updateCacheFrequency, indexDisableTimestamp, isNamespaceMapped, autoPartitionSeqName, isAppendOnlySchema, storageScheme, 
-                qualifierEncodingScheme, encodedCQCounter, useStatsForParallelization, excludedColumns);
-    }
-    
+
     @Override
     public long getUpdateCacheFrequency() {
         return updateCacheFrequency;
@@ -434,208 +843,14 @@ public class PTableImpl implements PTable {
         return viewType;
     }
 
-
     @Override
     public int getEstimatedSize() {
         return estimatedSize;
     }
 
-    private void init(PName tenantId, PName schemaName, PName tableName, PTableType type, PIndexState state, long timeStamp, long sequenceNumber,
-            PName pkName, Integer bucketNum, Collection<PColumn> columns, PName parentSchemaName, PName parentTableName,
-            List<PTable> indexes, boolean isImmutableRows, List<PName> physicalNames, PName defaultFamilyName, String viewExpression, boolean disableWAL,
-            boolean multiTenant, boolean storeNulls, ViewType viewType,PDataType viewIndexType,  Long viewIndexId,
-            IndexType indexType , int baseColumnCount, boolean rowKeyOrderOptimizable, TransactionFactory.Provider transactionProvider, long updateCacheFrequency, long indexDisableTimestamp, 
-            boolean isNamespaceMapped, String autoPartitionSeqName, boolean isAppendOnlySchema, ImmutableStorageScheme storageScheme, QualifierEncodingScheme qualifierEncodingScheme, 
-            EncodedCQCounter encodedCQCounter, Boolean useStatsForParallelization, Collection<PColumn> excludedColumns) throws SQLException {
-        Preconditions.checkNotNull(schemaName);
-        Preconditions.checkArgument(tenantId==null || tenantId.getBytes().length > 0); // tenantId should be null or not empty
-        int estimatedSize = SizedUtil.OBJECT_SIZE * 2 + 23 * SizedUtil.POINTER_SIZE + 4 * SizedUtil.INT_SIZE + 2 * SizedUtil.LONG_SIZE + 2 * SizedUtil.INT_OBJECT_SIZE +
-              PNameFactory.getEstimatedSize(tenantId) +
-              PNameFactory.getEstimatedSize(schemaName) +
-              PNameFactory.getEstimatedSize(tableName) +
-              PNameFactory.getEstimatedSize(pkName) +
-              PNameFactory.getEstimatedSize(parentTableName) +
-              PNameFactory.getEstimatedSize(defaultFamilyName);
-        this.tenantId = tenantId;
-        this.schemaName = schemaName;
-        this.tableName = tableName;
-        this.name = PNameFactory.newName(SchemaUtil.getTableName(schemaName.getString(), tableName.getString()));
-        this.key = new PTableKey(tenantId, name.getString());
-        this.type = type;
-        this.state = state;
-        this.timeStamp = timeStamp;
-        this.indexDisableTimestamp = indexDisableTimestamp;
-        this.sequenceNumber = sequenceNumber;
-        this.pkName = pkName;
-        this.isImmutableRows = isImmutableRows;
-        this.defaultFamilyName = defaultFamilyName;
-        this.viewStatement = viewExpression;
-        this.disableWAL = disableWAL;
-        this.multiTenant = multiTenant;
-        this.storeNulls = storeNulls;
-        this.viewType = viewType;
-        this.viewIndexType = viewIndexType;
-        this.viewIndexId = viewIndexId;
-        this.indexType = indexType;
-        this.transactionProvider = transactionProvider;
-        this.rowKeyOrderOptimizable = rowKeyOrderOptimizable;
-        this.updateCacheFrequency = updateCacheFrequency;
-        this.isNamespaceMapped = isNamespaceMapped;
-        this.autoPartitionSeqName = autoPartitionSeqName;
-        this.isAppendOnlySchema = isAppendOnlySchema;
-        // null check for backward compatibility and sanity. If any of the two below is null, then it means the table is a non-encoded table.
-        this.immutableStorageScheme = storageScheme == null ? ImmutableStorageScheme.ONE_CELL_PER_COLUMN : storageScheme;
-        this.qualifierEncodingScheme = qualifierEncodingScheme == null ? QualifierEncodingScheme.NON_ENCODED_QUALIFIERS : qualifierEncodingScheme;
-        List<PColumn> pkColumns;
-        PColumn[] allColumns;
-        
-        this.columnsByName = ArrayListMultimap.create(columns.size(), 1);
-        this.kvColumnsByQualifiers = Maps.newHashMapWithExpectedSize(columns.size());
-        int numPKColumns = 0;
-        if (bucketNum != null) {
-            // Add salt column to allColumns and pkColumns, but don't add to
-            // columnsByName, since it should not be addressable via name.
-            allColumns = new PColumn[columns.size()+1];
-            allColumns[SALTING_COLUMN.getPosition()] = SALTING_COLUMN;
-            pkColumns = Lists.newArrayListWithExpectedSize(columns.size()+1);
-            ++numPKColumns;
-        } else {
-            allColumns = new PColumn[columns.size()];
-            pkColumns = Lists.newArrayListWithExpectedSize(columns.size());
-        }
-        // Must do this as with the new method of storing diffs, we just care about ordinal position
-        // relative order and not the true ordinal value itself.
-        List<PColumn> sortedColumns = Lists.newArrayList(columns);
-        Collections.sort(sortedColumns, new Comparator<PColumn>() {
-            @Override
-            public int compare(PColumn o1, PColumn o2) {
-                return Integer.valueOf(o1.getPosition()).compareTo(o2.getPosition());
-            }
-        });
-
-        int position = 0;
-        if (bucketNum != null) {
-            position = 1;
-        }
-        for (PColumn column : sortedColumns) {
-            allColumns[position] = column;
-            position++;
-            PName familyName = column.getFamilyName();
-            if (familyName == null) {
-                ++numPKColumns;
-            }
-            String columnName = column.getName().getString();
-            if (columnsByName.put(columnName, column)) {
-                int count = 0;
-                for (PColumn dupColumn : columnsByName.get(columnName)) {
-                    if (Objects.equal(familyName, dupColumn.getFamilyName())) {
-                        count++;
-                        if (count > 1) {
-                            throw new ColumnAlreadyExistsException(schemaName.getString(), name.getString(), columnName);
-                        }
-                    }
-                }
-            }
-            byte[] cq = column.getColumnQualifierBytes();
-            String cf = column.getFamilyName() != null ? column.getFamilyName().getString() : null;
-            if (cf != null && cq != null) {
-                KVColumnFamilyQualifier info = new KVColumnFamilyQualifier(cf, cq);
-                if (kvColumnsByQualifiers.get(info) != null) {
-                    throw new ColumnAlreadyExistsException(schemaName.getString(),
-                            name.getString(), columnName);
-                }
-                kvColumnsByQualifiers.put(info, column);
-            }
-        }
-        estimatedSize += SizedUtil.sizeOfMap(allColumns.length, SizedUtil.POINTER_SIZE, SizedUtil.sizeOfArrayList(1)); // for multi-map
-
-        this.bucketNum = bucketNum;
-        this.allColumns = ImmutableList.copyOf(allColumns);
-        estimatedSize += SizedUtil.sizeOfMap(numPKColumns) + SizedUtil.sizeOfMap(allColumns.length);
-
-        RowKeySchemaBuilder builder = new RowKeySchemaBuilder(numPKColumns);
-        // Two pass so that column order in column families matches overall column order
-        // and to ensure that column family order is constant
-        int maxExpectedSize = allColumns.length - numPKColumns;
-        // Maintain iteration order so that column families are ordered as they are listed
-        Map<PName, List<PColumn>> familyMap = Maps.newLinkedHashMap();
-        PColumn rowTimestampCol = null;
-        for (PColumn column : allColumns) {
-            PName familyName = column.getFamilyName();
-            if (familyName == null) {
-                hasColumnsRequiringUpgrade |= 
-                        ( column.getSortOrder() == SortOrder.DESC 
-                            && (!column.getDataType().isFixedWidth() 
-                                || column.getDataType() == PChar.INSTANCE 
-                                || column.getDataType() == PFloat.INSTANCE 
-                                || column.getDataType() == PDouble.INSTANCE 
-                                || column.getDataType() == PBinary.INSTANCE) )
-                        || (column.getSortOrder() == SortOrder.ASC && column.getDataType() == PBinary.INSTANCE && column.getMaxLength() != null && column.getMaxLength() > 1);
-                pkColumns.add(column);
-                if (column.isRowTimestamp()) {
-                    rowTimestampCol = column;
-                }
-            }
-            if (familyName == null) {
-                estimatedSize += column.getEstimatedSize(); // PK columns
-                builder.addField(column, column.isNullable(), column.getSortOrder());
-            } else {
-                List<PColumn> columnsInFamily = familyMap.get(familyName);
-                if (columnsInFamily == null) {
-                    columnsInFamily = Lists.newArrayListWithExpectedSize(maxExpectedSize);
-                    familyMap.put(familyName, columnsInFamily);
-                }
-                columnsInFamily.add(column);
-            }
-        }
-        this.pkColumns = ImmutableList.copyOf(pkColumns);
-        if (rowTimestampCol != null) {
-            this.rowTimestampColPos = this.pkColumns.indexOf(rowTimestampCol);
-        } else {
-            this.rowTimestampColPos = -1;
-        }
-        
-        builder.rowKeyOrderOptimizable(this.rowKeyOrderOptimizable()); // after hasDescVarLengthColumns is calculated
-        this.rowKeySchema = builder.build();
-        estimatedSize += rowKeySchema.getEstimatedSize();
-        Iterator<Map.Entry<PName,List<PColumn>>> iterator = familyMap.entrySet().iterator();
-        PColumnFamily[] families = new PColumnFamily[familyMap.size()];
-        ImmutableMap.Builder<String, PColumnFamily> familyByString = ImmutableMap.builder();
-        ImmutableSortedMap.Builder<byte[], PColumnFamily> familyByBytes = ImmutableSortedMap
-                .orderedBy(Bytes.BYTES_COMPARATOR);
-        for (int i = 0; i < families.length; i++) {
-            Map.Entry<PName,List<PColumn>> entry = iterator.next();
-            PColumnFamily family = new PColumnFamilyImpl(entry.getKey(), entry.getValue());
-            families[i] = family;
-            familyByString.put(family.getName().getString(), family);
-            familyByBytes.put(family.getName().getBytes(), family);
-            estimatedSize += family.getEstimatedSize();
-        }
-        this.families = ImmutableList.copyOf(families);
-        this.familyByBytes = familyByBytes.build();
-        this.familyByString = familyByString.build();
-        estimatedSize += SizedUtil.sizeOfArrayList(families.length);
-        estimatedSize += SizedUtil.sizeOfMap(families.length) * 2;
-        this.indexes = indexes == null ? Collections.<PTable>emptyList() : indexes;
-        for (PTable index : this.indexes) {
-            estimatedSize += index.getEstimatedSize();
-        }
-
-        this.parentSchemaName = parentSchemaName;
-        this.parentTableName = parentTableName;
-        this.parentName = parentTableName == null ? null : PNameFactory.newName(SchemaUtil.getTableName(
-            parentSchemaName!=null ? parentSchemaName.getString() : null, parentTableName.getString()));
-        estimatedSize += PNameFactory.getEstimatedSize(this.parentName);
-
-        this.physicalNames = physicalNames == null ? ImmutableList.<PName>of() : ImmutableList.copyOf(physicalNames);
-        for (PName name : this.physicalNames) {
-            estimatedSize += name.getEstimatedSize();
-        }
-        this.estimatedSize = estimatedSize;
-        this.baseColumnCount = baseColumnCount;
-        this.encodedCQCounter = encodedCQCounter;
-        this.useStatsForParallelization = useStatsForParallelization;
-        this.excludedColumns = excludedColumns == null ? ImmutableList.<PColumn>of() : ImmutableList.copyOf(excludedColumns);
+    public static void checkTenantId(PName tenantId) {
+        // tenantId should be null or not empty
+        Preconditions.checkArgument(tenantId == null || tenantId.getBytes().length > 0);
     }
 
     @Override
@@ -1340,9 +1555,9 @@ public class PTableImpl implements PTable {
         if (table.hasIsNamespaceMapped()) {
             isNamespaceMapped = table.getIsNamespaceMapped();
         }
-        String autoParititonSeqName = null;
+        String autoPartitionSeqName = null;
         if (table.hasAutoParititonSeqName()) {
-            autoParititonSeqName = table.getAutoParititonSeqName();
+            autoPartitionSeqName = table.getAutoParititonSeqName();
         }
         boolean isAppendOnlySchema = false;
         if (table.hasIsAppendOnlySchema()) {
@@ -1358,7 +1573,7 @@ public class PTableImpl implements PTable {
         if (table.hasEncodingScheme()) {
             qualifierEncodingScheme = QualifierEncodingScheme.fromSerializedValue(table.getEncodingScheme().toByteArray()[0]);
         }
-        EncodedCQCounter encodedColumnQualifierCounter = null;
+        EncodedCQCounter encodedColumnQualifierCounter;
         if ((!EncodedColumnsUtil.usesEncodedColumnNames(qualifierEncodingScheme) || tableType == PTableType.VIEW)) {
             encodedColumnQualifierCounter = PTable.EncodedCQCounter.NULL_COUNTER;
         }
@@ -1375,14 +1590,50 @@ public class PTableImpl implements PTable {
             useStatsForParallelization = table.getUseStatsForParallelization();
         }
         try {
-            PTableImpl result = new PTableImpl();
-            result.init(tenantId, schemaName, tableName, tableType, indexState, timeStamp, sequenceNumber, pkName,
-                (bucketNum == NO_SALTING) ? null : bucketNum, columns, parentSchemaName, parentTableName, indexes,
-                        isImmutableRows, physicalNames, defaultFamilyName, viewStatement, disableWAL,
-                        multiTenant, storeNulls, viewType, viewIndexType, viewIndexId, indexType, baseColumnCount, rowKeyOrderOptimizable,
-                        transactionProvider, updateCacheFrequency, indexDisableTimestamp, isNamespaceMapped, autoParititonSeqName, 
-                        isAppendOnlySchema, storageScheme, qualifierEncodingScheme, encodedColumnQualifierCounter, useStatsForParallelization, null);
-            return result;
+            return new PTableImpl.Builder()
+                    .setType(tableType)
+                    .setState(indexState)
+                    .setTimeStamp(timeStamp)
+                    .setIndexDisableTimestamp(indexDisableTimestamp)
+                    .setSequenceNumber(sequenceNumber)
+                    .setImmutableRows(isImmutableRows)
+                    .setViewStatement(viewStatement)
+                    .setDisableWAL(disableWAL)
+                    .setMultiTenant(multiTenant)
+                    .setStoreNulls(storeNulls)
+                    .setViewType(viewType)
+                    .setViewIndexType(viewIndexType)
+                    .setViewIndexId(viewIndexId)
+                    .setIndexType(indexType)
+                    .setTransactionProvider(transactionProvider)
+                    .setUpdateCacheFrequency(updateCacheFrequency)
+                    .setNamespaceMapped(isNamespaceMapped)
+                    .setAutoPartitionSeqName(autoPartitionSeqName)
+                    .setAppendOnlySchema(isAppendOnlySchema)
+                    // null check for backward compatibility and sanity. If any of the two below is null,
+                    // then it means the table is a non-encoded table.
+                    .setImmutableStorageScheme(storageScheme == null ?
+                            ImmutableStorageScheme.ONE_CELL_PER_COLUMN : storageScheme)
+                    .setQualifierEncodingScheme(qualifierEncodingScheme == null ?
+                            QualifierEncodingScheme.NON_ENCODED_QUALIFIERS : qualifierEncodingScheme)
+                    .setBaseColumnCount(baseColumnCount)
+                    .setEncodedCQCounter(encodedColumnQualifierCounter)
+                    .setUseStatsForParallelization(useStatsForParallelization)
+                    .setExcludedColumns(ImmutableList.<PColumn>of())
+                    .setTenantId(tenantId)
+                    .setSchemaName(schemaName)
+                    .setTableName(tableName)
+                    .setPkName(pkName)
+                    .setDefaultFamilyName(defaultFamilyName)
+                    .setRowKeyOrderOptimizable(rowKeyOrderOptimizable)
+                    .setBucketNum((bucketNum == NO_SALTING) ? null : bucketNum)
+                    .setIndexes(indexes == null ? Collections.<PTable>emptyList() : indexes)
+                    .setParentSchemaName(parentSchemaName)
+                    .setParentTableName(parentTableName)
+                    .setPhysicalNames(physicalNames == null ?
+                            ImmutableList.<PName>of() : ImmutableList.copyOf(physicalNames))
+                    .setColumns(columns)
+                    .build();
         } catch (SQLException e) {
             throw new RuntimeException(e); // Impossible
         }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/02a6bbce/phoenix-core/src/main/java/org/apache/phoenix/schema/TableRef.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/TableRef.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/TableRef.java
index 37cae22..b40c0b8 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/TableRef.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/TableRef.java
@@ -17,6 +17,8 @@
  */
 package org.apache.phoenix.schema;
 
+import java.sql.SQLException;
+import java.util.Collections;
 import java.util.Objects;
 
 import org.apache.phoenix.compile.TupleProjectionCompiler;
@@ -28,7 +30,7 @@ import org.apache.phoenix.util.SchemaUtil;
 
 
 public class TableRef {
-    public static final TableRef EMPTY_TABLE_REF = new TableRef(new PTableImpl());
+    public static final TableRef EMPTY_TABLE_REF = createEmptyTableRef();
     
     private PTable table;
     private long upperBoundTimeStamp;
@@ -37,6 +39,19 @@ public class TableRef {
     private final boolean hasDynamicCols;
     private final long currentTime;
 
+    private static TableRef createEmptyTableRef() {
+        try {
+            return new TableRef(new PTableImpl.Builder()
+                    .setIndexes(Collections.<PTable>emptyList())
+                    .setPhysicalNames(Collections.<PName>emptyList())
+                    .setRowKeySchema(RowKeySchema.EMPTY_SCHEMA)
+                    .build());
+        } catch (SQLException e) {
+            // Should never happen
+            return null;
+        }
+    }
+
     public TableRef(TableRef tableRef) {
         this(tableRef.alias, tableRef.table, tableRef.upperBoundTimeStamp, tableRef.lowerBoundTimeStamp, tableRef.hasDynamicCols);
     }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/02a6bbce/phoenix-core/src/test/java/org/apache/phoenix/execute/CorrelatePlanTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/execute/CorrelatePlanTest.java b/phoenix-core/src/test/java/org/apache/phoenix/execute/CorrelatePlanTest.java
index 26caa0d..34f82d2 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/execute/CorrelatePlanTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/execute/CorrelatePlanTest.java
@@ -17,6 +17,7 @@
  */
 package org.apache.phoenix.execute;
 
+import static org.apache.phoenix.query.QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT;
 import static org.apache.phoenix.query.QueryConstants.VALUE_COLUMN_FAMILY;
 import static org.apache.phoenix.util.PhoenixRuntime.CONNECTIONLESS;
 import static org.apache.phoenix.util.PhoenixRuntime.JDBC_PROTOCOL;
@@ -30,6 +31,7 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 
+import com.google.common.collect.ImmutableList;
 import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.KeyValue;
 import org.apache.hadoop.hbase.client.Scan;
@@ -258,11 +260,31 @@ public class CorrelatePlanTest {
                     i, expr.getSortOrder(), null, null, false, name, false, false, colName.getBytes(), HConstants.LATEST_TIMESTAMP));
         }
         try {
-            PTable pTable = PTableImpl.makePTable(null, PName.EMPTY_NAME, PName.EMPTY_NAME,
-                    PTableType.SUBQUERY, null, MetaDataProtocol.MIN_TABLE_TIMESTAMP, PTable.INITIAL_SEQ_NUM,
-                    null, null, columns, null, null, Collections.<PTable>emptyList(),
-                    false, Collections.<PName>emptyList(), null, null, false, false, false, null, null,
-                    null, null, true, null, 0, 0L, Boolean.FALSE, null, false, ImmutableStorageScheme.ONE_CELL_PER_COLUMN, QualifierEncodingScheme.NON_ENCODED_QUALIFIERS, EncodedCQCounter.NULL_COUNTER, true);
+            PTable pTable =  new PTableImpl.Builder()
+                    .setType(PTableType.SUBQUERY)
+                    .setTimeStamp(MetaDataProtocol.MIN_TABLE_TIMESTAMP)
+                    .setIndexDisableTimestamp(0L)
+                    .setSequenceNumber(PTable.INITIAL_SEQ_NUM)
+                    .setImmutableRows(false)
+                    .setDisableWAL(false)
+                    .setMultiTenant(false)
+                    .setStoreNulls(false)
+                    .setUpdateCacheFrequency(0)
+                    .setNamespaceMapped(Boolean.FALSE)
+                    .setAppendOnlySchema(false)
+                    .setImmutableStorageScheme(ImmutableStorageScheme.ONE_CELL_PER_COLUMN)
+                    .setQualifierEncodingScheme(QualifierEncodingScheme.NON_ENCODED_QUALIFIERS)
+                    .setBaseColumnCount(BASE_TABLE_BASE_COLUMN_COUNT)
+                    .setEncodedCQCounter(EncodedCQCounter.NULL_COUNTER)
+                    .setUseStatsForParallelization(true)
+                    .setExcludedColumns(ImmutableList.<PColumn>of())
+                    .setSchemaName(PName.EMPTY_NAME)
+                    .setTableName(PName.EMPTY_NAME)
+                    .setRowKeyOrderOptimizable(true)
+                    .setIndexes(Collections.<PTable>emptyList())
+                    .setPhysicalNames(ImmutableList.<PName>of())
+                    .setColumns(columns)
+                    .build();
             TableRef sourceTable = new TableRef(pTable);
             List<ColumnRef> sourceColumnRefs = Lists.<ColumnRef> newArrayList();
             for (PColumn column : sourceTable.getTable().getColumns()) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/02a6bbce/phoenix-core/src/test/java/org/apache/phoenix/execute/LiteralResultIteratorPlanTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/execute/LiteralResultIteratorPlanTest.java b/phoenix-core/src/test/java/org/apache/phoenix/execute/LiteralResultIteratorPlanTest.java
index f400d0b..110bd26 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/execute/LiteralResultIteratorPlanTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/execute/LiteralResultIteratorPlanTest.java
@@ -17,6 +17,7 @@
  */
 package org.apache.phoenix.execute;
 
+import static org.apache.phoenix.query.QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT;
 import static org.apache.phoenix.query.QueryConstants.VALUE_COLUMN_FAMILY;
 import static org.apache.phoenix.util.PhoenixRuntime.CONNECTIONLESS;
 import static org.apache.phoenix.util.PhoenixRuntime.JDBC_PROTOCOL;
@@ -30,6 +31,7 @@ import java.sql.SQLException;
 import java.util.Collections;
 import java.util.List;
 
+import com.google.common.collect.ImmutableList;
 import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.KeyValue;
 import org.apache.hadoop.hbase.client.Scan;
@@ -181,12 +183,33 @@ public class LiteralResultIteratorPlanTest {
                 HConstants.LATEST_TIMESTAMP));
         }
         try {
-            PTable pTable = PTableImpl.makePTable(null, PName.EMPTY_NAME, PName.EMPTY_NAME, PTableType.SUBQUERY, null,
-                    MetaDataProtocol.MIN_TABLE_TIMESTAMP, PTable.INITIAL_SEQ_NUM, null, null, columns, null, null,
-                    Collections.<PTable> emptyList(), false, Collections.<PName> emptyList(), null, null, false, false,
-                    false, null, null, null, null, true, null, 0, 0L, false, null, false, ImmutableStorageScheme.ONE_CELL_PER_COLUMN, QualifierEncodingScheme.NON_ENCODED_QUALIFIERS, EncodedCQCounter.NULL_COUNTER, true);
+            PTable pTable = new PTableImpl.Builder()
+                    .setType(PTableType.SUBQUERY)
+                    .setTimeStamp(MetaDataProtocol.MIN_TABLE_TIMESTAMP)
+                    .setIndexDisableTimestamp(0L)
+                    .setSequenceNumber(PTable.INITIAL_SEQ_NUM)
+                    .setImmutableRows(false)
+                    .setDisableWAL(false)
+                    .setMultiTenant(false)
+                    .setStoreNulls(false)
+                    .setUpdateCacheFrequency(0)
+                    .setNamespaceMapped(false)
+                    .setAppendOnlySchema(false)
+                    .setImmutableStorageScheme(ImmutableStorageScheme.ONE_CELL_PER_COLUMN)
+                    .setQualifierEncodingScheme(QualifierEncodingScheme.NON_ENCODED_QUALIFIERS)
+                    .setBaseColumnCount(BASE_TABLE_BASE_COLUMN_COUNT)
+                    .setEncodedCQCounter(EncodedCQCounter.NULL_COUNTER)
+                    .setUseStatsForParallelization(true)
+                    .setExcludedColumns(ImmutableList.<PColumn>of())
+                    .setSchemaName(PName.EMPTY_NAME)
+                    .setTableName(PName.EMPTY_NAME)
+                    .setRowKeyOrderOptimizable(true)
+                    .setIndexes(Collections.<PTable>emptyList())
+                    .setPhysicalNames(ImmutableList.<PName>of())
+                    .setColumns(columns)
+                    .build();
             TableRef sourceTable = new TableRef(pTable);
-            List<ColumnRef> sourceColumnRefs = Lists.<ColumnRef> newArrayList();
+            List<ColumnRef> sourceColumnRefs = Lists.newArrayList();
             for (PColumn column : sourceTable.getTable().getColumns()) {
                 sourceColumnRefs.add(new ColumnRef(sourceTable, column.getPosition()));
             }


[2/2] phoenix git commit: PHOENIX-4996: Refactor PTableImpl to use Builder Pattern

Posted by td...@apache.org.
PHOENIX-4996: Refactor PTableImpl to use Builder Pattern


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/02a6bbce
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/02a6bbce
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/02a6bbce

Branch: refs/heads/4.x-HBase-1.2
Commit: 02a6bbce5a210278639e9d223ceb9a16cc645189
Parents: c509d58
Author: Chinmay Kulkarni <ch...@gmail.com>
Authored: Fri Nov 2 14:00:09 2018 -0700
Committer: Thomas D'Silva <td...@apache.org>
Committed: Tue Nov 6 15:19:05 2018 -0800

----------------------------------------------------------------------
 .../apache/phoenix/compile/DeleteCompiler.java  |    5 +-
 .../apache/phoenix/compile/FromCompiler.java    |   66 +-
 .../apache/phoenix/compile/JoinCompiler.java    |   53 +-
 .../compile/TupleProjectionCompiler.java        |   60 +-
 .../apache/phoenix/compile/UnionCompiler.java   |   41 +-
 .../apache/phoenix/compile/UpsertCompiler.java  |   12 +-
 .../coprocessor/MetaDataEndpointImpl.java       |   96 +-
 .../UngroupedAggregateRegionObserver.java       |    6 +-
 .../coprocessor/WhereConstantParser.java        |    3 +-
 .../query/ConnectionlessQueryServicesImpl.java  |    9 +-
 .../apache/phoenix/schema/MetaDataClient.java   |  215 ++-
 .../apache/phoenix/schema/PMetaDataImpl.java    |   28 +-
 .../org/apache/phoenix/schema/PTableImpl.java   | 1259 +++++++++++-------
 .../org/apache/phoenix/schema/TableRef.java     |   17 +-
 .../phoenix/execute/CorrelatePlanTest.java      |   32 +-
 .../execute/LiteralResultIteratorPlanTest.java  |   33 +-
 16 files changed, 1303 insertions(+), 632 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/02a6bbce/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java
index 583085e..8c9a930 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java
@@ -89,7 +89,6 @@ import org.apache.phoenix.schema.types.PLong;
 import org.apache.phoenix.transaction.PhoenixTransactionProvider.Feature;
 import org.apache.phoenix.util.ByteUtil;
 import org.apache.phoenix.util.IndexUtil;
-import org.apache.phoenix.util.MetaDataUtil;
 import org.apache.phoenix.util.ScanUtil;
 
 import com.google.common.base.Preconditions;
@@ -615,7 +614,9 @@ public class DeleteCompiler {
                     }
                 });
             }
-            PTable projectedTable = PTableImpl.makePTable(table, PTableType.PROJECTED, adjustedProjectedColumns);
+            PTable projectedTable = PTableImpl.builderWithColumns(table, adjustedProjectedColumns)
+                    .setType(PTableType.PROJECTED)
+                    .build();
             final TableRef projectedTableRef = new TableRef(projectedTable, targetTableRef.getLowerBoundTimeStamp(), targetTableRef.getTimeStamp());
 
             QueryPlan bestPlanToBe = dataPlan;

http://git-wip-us.apache.org/repos/asf/phoenix/blob/02a6bbce/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
index efc66a9..2701af0 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
@@ -32,8 +32,6 @@ import org.apache.hadoop.hbase.util.Bytes;
 import org.apache.phoenix.coprocessor.MetaDataProtocol;
 import org.apache.phoenix.coprocessor.MetaDataProtocol.MetaDataMutationResult;
 import org.apache.phoenix.coprocessor.MetaDataProtocol.MutationCode;
-import org.apache.phoenix.exception.SQLExceptionCode;
-import org.apache.phoenix.exception.SQLExceptionInfo;
 import org.apache.phoenix.expression.Expression;
 import org.apache.phoenix.jdbc.PhoenixConnection;
 import org.apache.phoenix.parse.AliasedNode;
@@ -82,6 +80,7 @@ import org.apache.phoenix.schema.PTableImpl;
 import org.apache.phoenix.schema.PTableKey;
 import org.apache.phoenix.schema.PTableType;
 import org.apache.phoenix.schema.ProjectedColumn;
+import org.apache.phoenix.schema.RowKeySchema;
 import org.apache.phoenix.schema.SchemaNotFoundException;
 import org.apache.phoenix.schema.SortOrder;
 import org.apache.phoenix.schema.TableNotFoundException;
@@ -284,7 +283,8 @@ public class FromCompiler {
                 column.getTimestamp());
             projectedColumns.add(projectedColumn);
         }
-        PTable t = PTableImpl.makePTable(table, projectedColumns);
+        PTable t = PTableImpl.builderWithColumns(table, projectedColumns)
+                .build();
         return new SingleTableColumnResolver(connection, new TableRef(tableRef.getTableAlias(), t, tableRef.getLowerBoundTimeStamp(), tableRef.hasDynamicCols()));
     }
     
@@ -369,10 +369,30 @@ public class FromCompiler {
             if (connection.getSchema() != null) {
                 schema = schema != null ? schema : connection.getSchema();
             }
+
             // Storage scheme and encoding scheme don't matter here since the PTable is being used only for the purposes of create table.
             // The actual values of these two will be determined by the metadata client.
-            PTable theTable = new PTableImpl(connection.getTenantId(), schema, table.getName().getTableName(),
-                    scn == null ? HConstants.LATEST_TIMESTAMP : scn, families, isNamespaceMapped);
+            PName tenantId = connection.getTenantId();
+            PTableImpl.checkTenantId(tenantId);
+            String tableName = table.getName().getTableName();
+            PName name = PNameFactory.newName(SchemaUtil.getTableName(schema, tableName));
+            PTable theTable = new PTableImpl.Builder()
+                    .setTenantId(tenantId)
+                    .setName(name)
+                    .setKey(new PTableKey(tenantId, name.getString()))
+                    .setSchemaName(PNameFactory.newName(schema))
+                    .setTableName(PNameFactory.newName(tableName))
+                    .setType(PTableType.VIEW)
+                    .setViewType(PTable.ViewType.MAPPED)
+                    .setTimeStamp(scn == null ? HConstants.LATEST_TIMESTAMP : scn)
+                    .setPkColumns(Collections.<PColumn>emptyList())
+                    .setAllColumns(Collections.<PColumn>emptyList())
+                    .setRowKeySchema(RowKeySchema.EMPTY_SCHEMA)
+                    .setIndexes(Collections.<PTable>emptyList())
+                    .setFamilyAttributes(families)
+                    .setPhysicalNames(Collections.<PName>emptyList())
+                    .setNamespaceMapped(isNamespaceMapped)
+                    .build();
             theTable = this.addDynamicColumns(table.getDynamicColumns(), theTable);
             alias = null;
             tableRefs = ImmutableList.of(new TableRef(alias, theTable, timeStamp, !table.getDynamicColumns().isEmpty()));
@@ -706,7 +726,7 @@ public class FromCompiler {
             if (!dynColumns.isEmpty()) {
                 List<PColumn> allcolumns = new ArrayList<PColumn>();
                 List<PColumn> existingColumns = theTable.getColumns();
-                // Need to skip the salting column, as it's added in the makePTable call below
+                // Need to skip the salting column, as it's handled in the PTable builder call below
                 allcolumns.addAll(theTable.getBucketNum() == null ? existingColumns : existingColumns.subList(1, existingColumns.size()));
                 // Position still based on with the salting columns
                 int position = existingColumns.size();
@@ -724,7 +744,8 @@ public class FromCompiler {
                         HConstants.LATEST_TIMESTAMP));
                     position++;
                 }
-                theTable = PTableImpl.makePTable(theTable, allcolumns);
+                theTable = PTableImpl.builderWithColumns(theTable, allcolumns)
+                        .build();
             }
             return theTable;
         }
@@ -830,11 +851,32 @@ public class FromCompiler {
                     HConstants.LATEST_TIMESTAMP);
                 columns.add(column);
             }
-            PTable t = PTableImpl.makePTable(null, PName.EMPTY_NAME, PName.EMPTY_NAME, PTableType.SUBQUERY, null,
-                    MetaDataProtocol.MIN_TABLE_TIMESTAMP, PTable.INITIAL_SEQ_NUM, null, null, columns, null, null,
-                    Collections.<PTable> emptyList(), false, Collections.<PName> emptyList(), null, null, false, false,
-                    false, null, null, null, null, false, null, 0, 0L, SchemaUtil
-                            .isNamespaceMappingEnabled(PTableType.SUBQUERY, connection.getQueryServices().getProps()), null, false, ImmutableStorageScheme.ONE_CELL_PER_COLUMN, QualifierEncodingScheme.NON_ENCODED_QUALIFIERS, PTable.EncodedCQCounter.NULL_COUNTER, true);
+            PTable t = new PTableImpl.Builder()
+                    .setType(PTableType.SUBQUERY)
+                    .setTimeStamp(MetaDataProtocol.MIN_TABLE_TIMESTAMP)
+                    .setIndexDisableTimestamp(0L)
+                    .setSequenceNumber(PTable.INITIAL_SEQ_NUM)
+                    .setImmutableRows(false)
+                    .setDisableWAL(false)
+                    .setMultiTenant(false)
+                    .setStoreNulls(false)
+                    .setUpdateCacheFrequency(0)
+                    .setNamespaceMapped(SchemaUtil.isNamespaceMappingEnabled(PTableType.SUBQUERY,
+                            connection.getQueryServices().getProps()))
+                    .setAppendOnlySchema(false)
+                    .setImmutableStorageScheme(ImmutableStorageScheme.ONE_CELL_PER_COLUMN)
+                    .setQualifierEncodingScheme(QualifierEncodingScheme.NON_ENCODED_QUALIFIERS)
+                    .setBaseColumnCount(QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT)
+                    .setEncodedCQCounter(PTable.EncodedCQCounter.NULL_COUNTER)
+                    .setUseStatsForParallelization(true)
+                    .setExcludedColumns(ImmutableList.<PColumn>of())
+                    .setSchemaName(PName.EMPTY_NAME)
+                    .setTableName(PName.EMPTY_NAME)
+                    .setRowKeyOrderOptimizable(false)
+                    .setIndexes(Collections.<PTable>emptyList())
+                    .setPhysicalNames(ImmutableList.<PName>of())
+                    .setColumns(columns)
+                    .build();
 
             String alias = subselectNode.getAlias();
             TableRef tableRef = new TableRef(alias, t, MetaDataProtocol.MIN_TABLE_TIMESTAMP, false);

http://git-wip-us.apache.org/repos/asf/phoenix/blob/02a6bbce/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java
index 880fa72..807e54b 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java
@@ -17,6 +17,7 @@
  */
 package org.apache.phoenix.compile;
 
+import static org.apache.phoenix.query.QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT;
 import static org.apache.phoenix.schema.PTable.ImmutableStorageScheme.ONE_CELL_PER_COLUMN;
 import static org.apache.phoenix.schema.PTable.QualifierEncodingScheme.NON_ENCODED_QUALIFIERS;
 
@@ -32,6 +33,7 @@ import java.util.ListIterator;
 import java.util.Map;
 import java.util.Set;
 
+import com.google.common.collect.ImmutableList;
 import org.apache.hadoop.hbase.client.Scan;
 import org.apache.hadoop.hbase.util.Pair;
 import org.apache.phoenix.exception.SQLExceptionCode;
@@ -71,8 +73,8 @@ import org.apache.phoenix.schema.ColumnRef;
 import org.apache.phoenix.schema.LocalIndexDataColumnRef;
 import org.apache.phoenix.schema.MetaDataEntityNotFoundException;
 import org.apache.phoenix.schema.PColumn;
-import org.apache.phoenix.schema.PName;
 import org.apache.phoenix.schema.PNameFactory;
+import org.apache.phoenix.schema.PName;
 import org.apache.phoenix.schema.PTable;
 import org.apache.phoenix.schema.PTable.IndexType;
 import org.apache.phoenix.schema.PTableImpl;
@@ -1270,17 +1272,44 @@ public class JoinCompiler {
         if (left.getBucketNum() != null) {
             merged.remove(0);
         }
-        return PTableImpl.makePTable(left.getTenantId(), left.getSchemaName(),
-                PNameFactory.newName(SchemaUtil.getTableName(left.getName().getString(), right.getName().getString())),
-                left.getType(), left.getIndexState(), left.getTimeStamp(), left.getSequenceNumber(), left.getPKName(),
-                left.getBucketNum(), merged, left.getParentSchemaName(), left.getParentTableName(), left.getIndexes(),
-                left.isImmutableRows(), Collections.<PName> emptyList(), null, null, PTable.DEFAULT_DISABLE_WAL,
-                left.isMultiTenant(), left.getStoreNulls(), left.getViewType(), left.getViewIndexType(), left.getViewIndexId(),
-                left.getIndexType(), left.rowKeyOrderOptimizable(), left.getTransactionProvider(),
-                left.getUpdateCacheFrequency(), left.getIndexDisableTimestamp(), left.isNamespaceMapped(), 
-                left.getAutoPartitionSeqName(), left.isAppendOnlySchema(), ONE_CELL_PER_COLUMN, NON_ENCODED_QUALIFIERS, PTable.EncodedCQCounter.NULL_COUNTER, left.useStatsForParallelization());
+        return new PTableImpl.Builder()
+                .setType(left.getType())
+                .setState(left.getIndexState())
+                .setTimeStamp(left.getTimeStamp())
+                .setIndexDisableTimestamp(left.getIndexDisableTimestamp())
+                .setSequenceNumber(left.getSequenceNumber())
+                .setImmutableRows(left.isImmutableRows())
+                .setDisableWAL(PTable.DEFAULT_DISABLE_WAL)
+                .setMultiTenant(left.isMultiTenant())
+                .setStoreNulls(left.getStoreNulls())
+                .setViewType(left.getViewType())
+                .setViewIndexType(left.getViewIndexType())
+                .setViewIndexId(left.getViewIndexId())
+                .setIndexType(left.getIndexType())
+                .setTransactionProvider(left.getTransactionProvider())
+                .setUpdateCacheFrequency(left.getUpdateCacheFrequency())
+                .setNamespaceMapped(left.isNamespaceMapped())
+                .setAutoPartitionSeqName(left.getAutoPartitionSeqName())
+                .setAppendOnlySchema(left.isAppendOnlySchema())
+                .setImmutableStorageScheme(ONE_CELL_PER_COLUMN)
+                .setQualifierEncodingScheme(NON_ENCODED_QUALIFIERS)
+                .setBaseColumnCount(BASE_TABLE_BASE_COLUMN_COUNT)
+                .setEncodedCQCounter(PTable.EncodedCQCounter.NULL_COUNTER)
+                .setUseStatsForParallelization(left.useStatsForParallelization())
+                .setExcludedColumns(ImmutableList.<PColumn>of())
+                .setTenantId(left.getTenantId())
+                .setSchemaName(left.getSchemaName())
+                .setTableName(PNameFactory.newName(SchemaUtil.getTableName(left.getName().getString(),
+                        right.getName().getString())))
+                .setPkName(left.getPKName())
+                .setRowKeyOrderOptimizable(left.rowKeyOrderOptimizable())
+                .setBucketNum(left.getBucketNum())
+                .setIndexes(left.getIndexes() == null ? Collections.<PTable>emptyList() : left.getIndexes())
+                .setParentSchemaName(left.getParentSchemaName())
+                .setParentTableName(left.getParentTableName())
+                .setPhysicalNames(ImmutableList.<PName>of())
+                .setColumns(merged)
+                .build();
     }
 
 }
-
-

http://git-wip-us.apache.org/repos/asf/phoenix/blob/02a6bbce/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java
index dc85bd3..5b92a5d 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java
@@ -17,6 +17,8 @@
  */
 package org.apache.phoenix.compile;
 import static org.apache.phoenix.query.QueryConstants.VALUE_COLUMN_FAMILY;
+import static org.apache.phoenix.query.QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT;
+import static org.apache.phoenix.schema.PTable.ImmutableStorageScheme;
 
 import java.sql.SQLException;
 import java.util.ArrayList;
@@ -26,6 +28,7 @@ import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
 
+import com.google.common.collect.ImmutableList;
 import org.apache.phoenix.parse.AliasedNode;
 import org.apache.phoenix.parse.ColumnParseNode;
 import org.apache.phoenix.parse.FamilyWildcardParseNode;
@@ -160,15 +163,13 @@ public class TupleProjectionCompiler {
                     sourceColumnRef.getColumn().isNullable(), sourceColumnRef, sourceColumnRef.getColumn().getColumnQualifierBytes());
             projectedColumns.add(column);
         }
-        
-        return PTableImpl.makePTable(table.getTenantId(), table.getSchemaName(), table.getTableName(),
-                PTableType.PROJECTED, table.getIndexState(), table.getTimeStamp(), table.getSequenceNumber(),
-                table.getPKName(), table.getBucketNum(), projectedColumns, table.getParentSchemaName(),
-                table.getParentTableName(), table.getIndexes(), table.isImmutableRows(), Collections.<PName> emptyList(),
-                table.getDefaultFamilyName(), table.getViewStatement(), table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(),
-                table.getViewIndexType(), table.getViewIndexId(),
-                table.getIndexType(), table.rowKeyOrderOptimizable(), table.getTransactionProvider(), table.getUpdateCacheFrequency(), 
-                table.getIndexDisableTimestamp(), table.isNamespaceMapped(), table.getAutoPartitionSeqName(), table.isAppendOnlySchema(), table.getImmutableStorageScheme(), table.getEncodingScheme(), table.getEncodedCQCounter(), table.useStatsForParallelization());
+        return PTableImpl.builderWithColumns(table, projectedColumns)
+                .setType(PTableType.PROJECTED)
+                .setBaseColumnCount(BASE_TABLE_BASE_COLUMN_COUNT)
+                .setExcludedColumns(ImmutableList.<PColumn>of())
+                .setPhysicalNames(ImmutableList.<PName>of())
+                .setColumns(projectedColumns)
+                .build();
     }
     
     public static PTable createProjectedTable(TableRef tableRef, List<ColumnRef> sourceColumnRefs, boolean retainPKColumns) throws SQLException {
@@ -192,14 +193,39 @@ public class TupleProjectionCompiler {
         if (EncodedColumnsUtil.usesEncodedColumnNames(table)) {
             cqCounter = EncodedCQCounter.copy(table.getEncodedCQCounter());
         }
-        
-        return PTableImpl.makePTable(table.getTenantId(), PROJECTED_TABLE_SCHEMA, table.getName(), PTableType.PROJECTED,
-                null, table.getTimeStamp(), table.getSequenceNumber(), table.getPKName(),
-                table.getBucketNum(), projectedColumns, null, null,
-                Collections.<PTable> emptyList(), table.isImmutableRows(), Collections.<PName> emptyList(), null, null,
-                table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(),
-                table.getViewIndexType(), table.getViewIndexId(), null, table.rowKeyOrderOptimizable(), table.getTransactionProvider(),
-                table.getUpdateCacheFrequency(), table.getIndexDisableTimestamp(), table.isNamespaceMapped(), table.getAutoPartitionSeqName(), table.isAppendOnlySchema(), table.getImmutableStorageScheme(), table.getEncodingScheme(), cqCounter, table.useStatsForParallelization());
+        return new PTableImpl.Builder()
+                .setType(PTableType.PROJECTED)
+                .setTimeStamp(table.getTimeStamp())
+                .setIndexDisableTimestamp(table.getIndexDisableTimestamp())
+                .setSequenceNumber(table.getSequenceNumber())
+                .setImmutableRows(table.isImmutableRows())
+                .setDisableWAL(table.isWALDisabled())
+                .setMultiTenant(table.isMultiTenant())
+                .setStoreNulls(table.getStoreNulls())
+                .setViewType(table.getViewType())
+                .setViewIndexType(table.getViewIndexType())
+                .setViewIndexId(table.getViewIndexId())
+                .setTransactionProvider(table.getTransactionProvider())
+                .setUpdateCacheFrequency(table.getUpdateCacheFrequency())
+                .setNamespaceMapped(table.isNamespaceMapped())
+                .setAutoPartitionSeqName(table.getAutoPartitionSeqName())
+                .setAppendOnlySchema(table.isAppendOnlySchema())
+                .setImmutableStorageScheme(table.getImmutableStorageScheme())
+                .setQualifierEncodingScheme(table.getEncodingScheme())
+                .setBaseColumnCount(BASE_TABLE_BASE_COLUMN_COUNT)
+                .setEncodedCQCounter(cqCounter)
+                .setUseStatsForParallelization(table.useStatsForParallelization())
+                .setExcludedColumns(ImmutableList.<PColumn>of())
+                .setTenantId(table.getTenantId())
+                .setSchemaName(PROJECTED_TABLE_SCHEMA)
+                .setTableName(table.getTableName())
+                .setPkName(table.getPKName())
+                .setRowKeyOrderOptimizable(table.rowKeyOrderOptimizable())
+                .setBucketNum(table.getBucketNum())
+                .setIndexes(Collections.<PTable>emptyList())
+                .setPhysicalNames(ImmutableList.<PName>of())
+                .setColumns(projectedColumns)
+                .build();
     }
 
     // For extracting column references from single select statement

http://git-wip-us.apache.org/repos/asf/phoenix/blob/02a6bbce/phoenix-core/src/main/java/org/apache/phoenix/compile/UnionCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/UnionCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/UnionCompiler.java
index c0c63eb..a54fbdd 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/UnionCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/UnionCompiler.java
@@ -17,10 +17,14 @@
  */
 package org.apache.phoenix.compile;
 
+import static org.apache.phoenix.query.QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT;
+
 import java.sql.SQLException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
+import com.google.common.collect.ImmutableList;
 import org.apache.hadoop.hbase.HConstants;
 import org.apache.phoenix.exception.SQLExceptionCode;
 import org.apache.phoenix.exception.SQLExceptionInfo;
@@ -96,15 +100,34 @@ public class UnionCompiler {
             projectedColumns.add(projectedColumn);
         }
         Long scn = statement.getConnection().getSCN();
-        PTable tempTable = PTableImpl.makePTable(statement.getConnection().getTenantId(),
-            UNION_SCHEMA_NAME, UNION_TABLE_NAME, PTableType.SUBQUERY, null,
-            HConstants.LATEST_TIMESTAMP, scn == null ? HConstants.LATEST_TIMESTAMP : scn,
-            null, null, projectedColumns, null, null, null, true, null, null, null, true,
-            true, true, null, null, null, null, false, null, 0, 0L,
-            SchemaUtil.isNamespaceMappingEnabled(PTableType.SUBQUERY,
-                statement.getConnection().getQueryServices().getProps()), null, false, ImmutableStorageScheme.ONE_CELL_PER_COLUMN, QualifierEncodingScheme.NON_ENCODED_QUALIFIERS, PTable.EncodedCQCounter.NULL_COUNTER, true);
-        TableRef tableRef = new TableRef(null, tempTable, 0, false);
-        return tableRef;
+        PTable tempTable = new PTableImpl.Builder()
+                .setType(PTableType.SUBQUERY)
+                .setTimeStamp(HConstants.LATEST_TIMESTAMP)
+                .setIndexDisableTimestamp(0L)
+                .setSequenceNumber(scn == null ? HConstants.LATEST_TIMESTAMP : scn)
+                .setImmutableRows(true)
+                .setDisableWAL(true)
+                .setMultiTenant(true)
+                .setStoreNulls(true)
+                .setUpdateCacheFrequency(0)
+                .setNamespaceMapped(SchemaUtil.isNamespaceMappingEnabled(PTableType.SUBQUERY,
+                        statement.getConnection().getQueryServices().getProps()))
+                .setAppendOnlySchema(false)
+                .setImmutableStorageScheme(ImmutableStorageScheme.ONE_CELL_PER_COLUMN)
+                .setQualifierEncodingScheme(QualifierEncodingScheme.NON_ENCODED_QUALIFIERS)
+                .setBaseColumnCount(BASE_TABLE_BASE_COLUMN_COUNT)
+                .setEncodedCQCounter(PTable.EncodedCQCounter.NULL_COUNTER)
+                .setUseStatsForParallelization(true)
+                .setExcludedColumns(ImmutableList.<PColumn>of())
+                .setTenantId(statement.getConnection().getTenantId())
+                .setSchemaName(UNION_SCHEMA_NAME)
+                .setTableName(UNION_TABLE_NAME)
+                .setRowKeyOrderOptimizable(false)
+                .setIndexes(Collections.<PTable>emptyList())
+                .setPhysicalNames(ImmutableList.<PName>of())
+                .setColumns(projectedColumns)
+                .build();
+        return new TableRef(null, tempTable, 0, false);
     }
 
     private static void compareExperssions(int i, Expression expression,

http://git-wip-us.apache.org/repos/asf/phoenix/blob/02a6bbce/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java
index 61be561..4ed0c9a 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java
@@ -32,6 +32,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import com.google.common.collect.ImmutableList;
 import org.apache.hadoop.hbase.Cell;
 import org.apache.hadoop.hbase.HRegionLocation;
 import org.apache.hadoop.hbase.client.Scan;
@@ -701,9 +702,11 @@ public class UpsertCompiler {
                     }
                     // Build table from projectedColumns
                     // Hack to add default column family to be used on server in case no value column is projected.
-                    PTable projectedTable = PTableImpl.makePTable(table, projectedColumns,
-                            PNameFactory.newName(SchemaUtil.getEmptyColumnFamily(table)));  
-                    
+                    PTable projectedTable = PTableImpl.builderWithColumns(table, projectedColumns)
+                            .setExcludedColumns(ImmutableList.<PColumn>of())
+                            .setDefaultFamilyName(PNameFactory.newName(SchemaUtil.getEmptyColumnFamily(table)))
+                            .setColumns(projectedColumns)
+                            .build();
                     
                     SelectStatement select = SelectStatement.create(SelectStatement.COUNT_ONE, upsert.getHint());
                     StatementContext statementContext = queryPlan.getContext();
@@ -856,7 +859,8 @@ public class UpsertCompiler {
                     }
                     updateExpressions.add(updateExpression);
                 }
-                PTable onDupKeyTable = PTableImpl.makePTable(table, updateColumns);
+                PTable onDupKeyTable = PTableImpl.builderWithColumns(table, updateColumns)
+                        .build();
                 onDupKeyBytesToBe = PhoenixIndexBuilder.serializeOnDupKeyUpdate(onDupKeyTable, updateExpressions);
             }
         }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/02a6bbce/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
index 424b6d6..d899e32 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
@@ -78,6 +78,7 @@ import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.VIEW_INDEX_ID_DATA
 import static org.apache.phoenix.query.QueryConstants.DIVERGED_VIEW_BASE_COLUMN_COUNT;
 import static org.apache.phoenix.schema.PTableType.INDEX;
 import static org.apache.phoenix.schema.PTableType.TABLE;
+import static org.apache.phoenix.schema.PTableImpl.getColumnsToClone;
 import static org.apache.phoenix.util.SchemaUtil.getVarCharLength;
 import static org.apache.phoenix.util.SchemaUtil.getVarChars;
 
@@ -101,6 +102,7 @@ import java.util.NavigableMap;
 import java.util.Properties;
 import java.util.Set;
 
+import com.google.common.collect.ImmutableList;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hbase.Cell;
 import org.apache.hadoop.hbase.CellUtil;
@@ -215,6 +217,7 @@ import org.apache.phoenix.schema.PTableImpl;
 import org.apache.phoenix.schema.PTableKey;
 import org.apache.phoenix.schema.PTableType;
 import org.apache.phoenix.schema.ParentTableNotFoundException;
+import org.apache.phoenix.schema.RowKeySchema;
 import org.apache.phoenix.schema.SaltingUtil;
 import org.apache.phoenix.schema.SequenceAllocation;
 import org.apache.phoenix.schema.SequenceAlreadyExistsException;
@@ -689,7 +692,9 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
                     }
                     indexes.add(latestIndex);
                 }
-                table = PTableImpl.makePTable(table, table.getTimeStamp(), indexes);
+                table = PTableImpl.builderWithColumns(table, getColumnsToClone(table))
+                        .setIndexes(indexes == null ? Collections.<PTable>emptyList() : indexes)
+                        .build();
             }
         }
         
@@ -939,11 +944,31 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
         int baseTableColumnCount =
                 isDiverged ? QueryConstants.DIVERGED_VIEW_BASE_COLUMN_COUNT
                         : columnsToAdd.size() - myColumns.size() + (isSalted ? 1 : 0);
+
+        // When creating a PTable for views or view indexes, use the baseTable PTable for attributes
+        // inherited from the physical base table.
+        // if a TableProperty is not valid on a view we set it to the base table value
+        // if a TableProperty is valid on a view and is not mutable on a view we set it to the base table value
+        // if a TableProperty is valid on a view and is mutable on a view we use the value set on the view
         // TODO Implement PHOENIX-4763 to set the view properties correctly instead of just
         // setting them same as the base table
-        PTableImpl pTable =
-                PTableImpl.makePTable(table, baseTable, columnsToAdd, maxTableTimestamp,
-                    baseTableColumnCount, excludedColumns);
+        PTableImpl pTable = PTableImpl.builderWithColumns(table, columnsToAdd)
+                .setImmutableRows(baseTable.isImmutableRows())
+                .setDisableWAL(baseTable.isWALDisabled())
+                .setMultiTenant(baseTable.isMultiTenant())
+                .setStoreNulls(baseTable.getStoreNulls())
+                .setTransactionProvider(baseTable.getTransactionProvider())
+                .setAutoPartitionSeqName(baseTable.getAutoPartitionSeqName())
+                .setAppendOnlySchema(baseTable.isAppendOnlySchema())
+                .setImmutableStorageScheme(baseTable.getImmutableStorageScheme() == null ?
+                        ImmutableStorageScheme.ONE_CELL_PER_COLUMN : baseTable.getImmutableStorageScheme())
+                .setQualifierEncodingScheme(baseTable.getEncodingScheme() == null ?
+                        QualifierEncodingScheme.NON_ENCODED_QUALIFIERS : baseTable.getEncodingScheme())
+                .setBaseColumnCount(baseTableColumnCount)
+                .setTimeStamp(maxTableTimestamp)
+                .setExcludedColumns(excludedColumns == null ?
+                        ImmutableList.<PColumn>of() : ImmutableList.copyOf(excludedColumns))
+                .build();
         return WhereConstantParser.addViewInfoToPColumnsIfNeeded(pTable);
     }
 
@@ -1486,11 +1511,48 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
         }
         // Avoid querying the stats table because we're holding the rowLock here. Issuing an RPC to a remote
         // server while holding this lock is a bad idea and likely to cause contention.
-        return PTableImpl.makePTable(tenantId, schemaName, tableName, tableType, indexState, timeStamp, tableSeqNum,
-                pkName, saltBucketNum, columns, parentSchemaName, parentTableName, indexes, isImmutableRows, physicalTables, defaultFamilyName,
-                viewStatement, disableWAL, multiTenant, storeNulls, viewType, viewIndexType, viewIndexId, indexType,
-                rowKeyOrderOptimizable, transactionProvider, updateCacheFrequency, baseColumnCount,
-                indexDisableTimestamp, isNamespaceMapped, autoPartitionSeq, isAppendOnlySchema, storageScheme, encodingScheme, cqCounter, useStatsForParallelization);
+        return new PTableImpl.Builder()
+                .setType(tableType)
+                .setState(indexState)
+                .setTimeStamp(timeStamp)
+                .setIndexDisableTimestamp(indexDisableTimestamp)
+                .setSequenceNumber(tableSeqNum)
+                .setImmutableRows(isImmutableRows)
+                .setViewStatement(viewStatement)
+                .setDisableWAL(disableWAL)
+                .setMultiTenant(multiTenant)
+                .setStoreNulls(storeNulls)
+                .setViewType(viewType)
+                .setViewIndexType(viewIndexType)
+                .setViewIndexId(viewIndexId)
+                .setIndexType(indexType)
+                .setTransactionProvider(transactionProvider)
+                .setUpdateCacheFrequency(updateCacheFrequency)
+                .setNamespaceMapped(isNamespaceMapped)
+                .setAutoPartitionSeqName(autoPartitionSeq)
+                .setAppendOnlySchema(isAppendOnlySchema)
+                .setImmutableStorageScheme(storageScheme == null ?
+                        ImmutableStorageScheme.ONE_CELL_PER_COLUMN : storageScheme)
+                .setQualifierEncodingScheme(encodingScheme == null ?
+                        QualifierEncodingScheme.NON_ENCODED_QUALIFIERS : encodingScheme)
+                .setBaseColumnCount(baseColumnCount)
+                .setEncodedCQCounter(cqCounter)
+                .setUseStatsForParallelization(useStatsForParallelization)
+                .setExcludedColumns(ImmutableList.<PColumn>of())
+                .setTenantId(tenantId)
+                .setSchemaName(schemaName)
+                .setTableName(tableName)
+                .setPkName(pkName)
+                .setDefaultFamilyName(defaultFamilyName)
+                .setRowKeyOrderOptimizable(rowKeyOrderOptimizable)
+                .setBucketNum(saltBucketNum)
+                .setIndexes(indexes == null ? Collections.<PTable>emptyList() : indexes)
+                .setParentSchemaName(parentSchemaName)
+                .setParentTableName(parentTableName)
+                .setPhysicalNames(physicalTables == null ?
+                        ImmutableList.<PName>of() : ImmutableList.copyOf(physicalTables))
+                .setColumns(columns)
+                .build();
     }
     private Long getViewIndexId(Cell[] tableKeyValues, PDataType viewIndexType) {
         Cell viewIndexIdKv = tableKeyValues[VIEW_INDEX_ID_INDEX];
@@ -1740,7 +1802,21 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
     }
 
     private static PTable newDeletedTableMarker(long timestamp) {
-        return new PTableImpl(timestamp);
+        try {
+            return new PTableImpl.Builder()
+                    .setType(PTableType.TABLE)
+                    .setTimeStamp(timestamp)
+                    .setPkColumns(Collections.<PColumn>emptyList())
+                    .setAllColumns(Collections.<PColumn>emptyList())
+                    .setFamilyAttributes(Collections.<PColumnFamily>emptyList())
+                    .setRowKeySchema(RowKeySchema.EMPTY_SCHEMA)
+                    .setIndexes(Collections.<PTable>emptyList())
+                    .setPhysicalNames(Collections.<PName>emptyList())
+                    .build();
+        } catch (SQLException e) {
+            // Should never happen
+            return null;
+        }
     }
 
     private static PFunction newDeletedFunctionMarker(long timestamp) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/02a6bbce/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java
index a667316..73386a2 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java
@@ -23,6 +23,7 @@ import static org.apache.phoenix.query.QueryConstants.SINGLE_COLUMN_FAMILY;
 import static org.apache.phoenix.query.QueryConstants.UNGROUPED_AGG_ROW_KEY;
 import static org.apache.phoenix.query.QueryServices.MUTATE_BATCH_SIZE_ATTRIB;
 import static org.apache.phoenix.query.QueryServices.MUTATE_BATCH_SIZE_BYTES_ATTRIB;
+import static org.apache.phoenix.schema.PTableImpl.getColumnsToClone;
 import static org.apache.phoenix.schema.stats.StatisticsCollectionRunTracker.COMPACTION_UPDATE_STATS_ROW_COUNT;
 import static org.apache.phoenix.schema.stats.StatisticsCollectionRunTracker.CONCURRENT_UPDATE_STATS_ROW_COUNT;
 
@@ -411,7 +412,10 @@ public class UngroupedAggregateRegionObserver extends BaseScannerRegionObserver
             logger.debug("Upgrading row key for " + region.getRegionInfo().getTable().getNameAsString());
             projectedTable = deserializeTable(descRowKeyTableBytes);
             try {
-                writeToTable = PTableImpl.makePTable(projectedTable, true);
+                writeToTable = PTableImpl.builderWithColumns(projectedTable,
+                        getColumnsToClone(projectedTable))
+                        .setRowKeyOrderOptimizable(true)
+                        .build();
             } catch (SQLException e) {
                 ServerUtil.throwIOException("Upgrade failed", e); // Impossible
             }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/02a6bbce/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/WhereConstantParser.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/WhereConstantParser.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/WhereConstantParser.java
index 4528f55..9fc030c 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/WhereConstantParser.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/WhereConstantParser.java
@@ -94,7 +94,8 @@ public class WhereConstantParser {
                 result.add(column);
             }
         }
-        return PTableImpl.makePTable(view, result);
+        return PTableImpl.builderWithColumns(view, result)
+                .build();
     }
 
     private static PhoenixConnection getConnectionlessConnection() throws SQLException {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/02a6bbce/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java
index 655de0d..d7e7d6d 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java
@@ -18,6 +18,7 @@
 package org.apache.phoenix.query;
 
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.INDEX_STATE_BYTES;
+import static org.apache.phoenix.schema.PTableImpl.getColumnsToClone;
 
 import java.sql.SQLException;
 import java.util.ArrayList;
@@ -316,7 +317,8 @@ public class ConnectionlessQueryServicesImpl extends DelegateQueryServices imple
     public MetaDataMutationResult addColumn(List<Mutation> tableMetaData, PTable table, Map<String, List<Pair<String,Object>>> properties, Set<String> colFamiliesForPColumnsToBeAdded, List<PColumn> columnsToBeAdded) throws SQLException {
         List<PColumn> columns = Lists.newArrayList(table.getColumns());
         columns.addAll(columnsToBeAdded);
-        return new MetaDataMutationResult(MutationCode.TABLE_ALREADY_EXISTS, 0, PTableImpl.makePTable(table, columns));
+        return new MetaDataMutationResult(MutationCode.TABLE_ALREADY_EXISTS, 0,
+                PTableImpl.builderWithColumns(table, columns).build());
     }
 
     @Override
@@ -453,7 +455,10 @@ public class ConnectionlessQueryServicesImpl extends DelegateQueryServices imple
         String indexTableName = SchemaUtil.getTableName(schemaName, indexName);
         PName tenantId = tenantIdBytes.length == 0 ? null : PNameFactory.newName(tenantIdBytes);
         PTable index = metaData.getTableRef(new PTableKey(tenantId, indexTableName)).getTable();
-        index = PTableImpl.makePTable(index,newState == PIndexState.USABLE ? PIndexState.ACTIVE : newState == PIndexState.UNUSABLE ? PIndexState.INACTIVE : newState);
+        index = PTableImpl.builderWithColumns(index, getColumnsToClone(index))
+                .setState(newState == PIndexState.USABLE ? PIndexState.ACTIVE :
+                        newState == PIndexState.UNUSABLE ? PIndexState.INACTIVE : newState)
+                .build();
         return new MetaDataMutationResult(MutationCode.TABLE_ALREADY_EXISTS, 0, index);
     }
 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/02a6bbce/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
index df0e5d4..aae9fc4 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
@@ -104,6 +104,7 @@ import static org.apache.phoenix.schema.PTable.ImmutableStorageScheme.ONE_CELL_P
 import static org.apache.phoenix.schema.PTable.ImmutableStorageScheme.SINGLE_CELL_ARRAY_WITH_OFFSETS;
 import static org.apache.phoenix.schema.PTable.QualifierEncodingScheme.NON_ENCODED_QUALIFIERS;
 import static org.apache.phoenix.schema.PTable.ViewType.MAPPED;
+import static org.apache.phoenix.schema.PTableImpl.getColumnsToClone;
 import static org.apache.phoenix.schema.PTableType.TABLE;
 import static org.apache.phoenix.schema.PTableType.VIEW;
 import static org.apache.phoenix.schema.types.PDataType.FALSE_BYTES;
@@ -132,6 +133,7 @@ import java.util.Properties;
 import java.util.Set;
 
 import org.apache.hadoop.hbase.HColumnDescriptor;
+import com.google.common.base.Objects;
 import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.HTableDescriptor;
 import org.apache.hadoop.hbase.client.ClusterConnection;
@@ -247,6 +249,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ListMultimap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
@@ -931,10 +934,21 @@ public class MetaDataClient {
                     + QueryConstants.CHILD_VIEW_INDEX_NAME_SEPARATOR + index.getName().getString());
                 // add the index table with a new name so that it does not conflict with the existing index table
                 // and set update cache frequency to that of the view
-                indexesToAdd.add(PTableImpl.makePTable(index, modifiedIndexName, viewStatement, view.getUpdateCacheFrequency(), view.getTenantId()));
+                if (Objects.equal(viewStatement, index.getViewStatement())) {
+                    indexesToAdd.add(index);
+                } else {
+                    indexesToAdd.add(PTableImpl.builderWithColumns(index, getColumnsToClone(index))
+                            .setTableName(modifiedIndexName)
+                            .setViewStatement(viewStatement)
+                            .setUpdateCacheFrequency(view.getUpdateCacheFrequency())
+                            .setTenantId(view.getTenantId())
+                            .build());
+                }
             }
         }
-        PTable allIndexesTable = PTableImpl.makePTable(view, view.getTimeStamp(), indexesToAdd);
+        PTable allIndexesTable = PTableImpl.builderWithColumns(view, getColumnsToClone(view))
+                .setIndexes(indexesToAdd == null ? Collections.<PTable>emptyList() : indexesToAdd)
+                .build();
         result.setTable(allIndexesTable);
         return true;
     }
@@ -2650,13 +2664,38 @@ public class MetaDataClient {
                 // TODO: what about stats for system catalog?
                 PName newSchemaName = PNameFactory.newName(schemaName);
                 // Column names and qualifiers and hardcoded for system tables.
-                PTable table = PTableImpl.makePTable(tenantId,newSchemaName, PNameFactory.newName(tableName), tableType,
-                        null, MetaDataProtocol.MIN_TABLE_TIMESTAMP, PTable.INITIAL_SEQ_NUM,
-                        PNameFactory.newName(QueryConstants.SYSTEM_TABLE_PK_NAME), null, columns.values(), null, null,
-                        Collections.<PTable>emptyList(), isImmutableRows,
-                        Collections.<PName>emptyList(), defaultFamilyName == null ? null :
-                                PNameFactory.newName(defaultFamilyName), null,
-                        Boolean.TRUE.equals(disableWAL), false, false, null, viewIndexType, null, indexType, true, null, 0, 0L, isNamespaceMapped, autoPartitionSeq, isAppendOnlySchema, ONE_CELL_PER_COLUMN, NON_ENCODED_QUALIFIERS, PTable.EncodedCQCounter.NULL_COUNTER, true);
+                PTable table = new PTableImpl.Builder()
+                        .setType(tableType)
+                        .setTimeStamp(MetaDataProtocol.MIN_TABLE_TIMESTAMP)
+                        .setIndexDisableTimestamp(0L)
+                        .setSequenceNumber(PTable.INITIAL_SEQ_NUM)
+                        .setImmutableRows(isImmutableRows)
+                        .setDisableWAL(Boolean.TRUE.equals(disableWAL))
+                        .setMultiTenant(false)
+                        .setStoreNulls(false)
+                        .setViewIndexType(viewIndexType)
+                        .setIndexType(indexType)
+                        .setUpdateCacheFrequency(0)
+                        .setNamespaceMapped(isNamespaceMapped)
+                        .setAutoPartitionSeqName(autoPartitionSeq)
+                        .setAppendOnlySchema(isAppendOnlySchema)
+                        .setImmutableStorageScheme(ONE_CELL_PER_COLUMN)
+                        .setQualifierEncodingScheme(NON_ENCODED_QUALIFIERS)
+                        .setBaseColumnCount(QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT)
+                        .setEncodedCQCounter(PTable.EncodedCQCounter.NULL_COUNTER)
+                        .setUseStatsForParallelization(true)
+                        .setExcludedColumns(ImmutableList.<PColumn>of())
+                        .setTenantId(tenantId)
+                        .setSchemaName(newSchemaName)
+                        .setTableName(PNameFactory.newName(tableName))
+                        .setPkName(PNameFactory.newName(QueryConstants.SYSTEM_TABLE_PK_NAME))
+                        .setDefaultFamilyName(defaultFamilyName == null ? null :
+                                PNameFactory.newName(defaultFamilyName))
+                        .setRowKeyOrderOptimizable(true)
+                        .setIndexes(Collections.<PTable>emptyList())
+                        .setPhysicalNames(ImmutableList.<PName>of())
+                        .setColumns(columns.values())
+                        .build();
                 connection.addTable(table, MetaDataProtocol.MIN_TABLE_TIMESTAMP);
             }
             
@@ -2930,12 +2969,49 @@ public class MetaDataClient {
                  * for extra safety.
                  */
                 EncodedCQCounter cqCounterToBe = tableType == PTableType.VIEW ? NULL_COUNTER : cqCounter;
-                PTable table =  PTableImpl.makePTable(
-                        tenantId, newSchemaName, PNameFactory.newName(tableName), tableType, indexState, timestamp!=null ? timestamp : result.getMutationTime(),
-                        PTable.INITIAL_SEQ_NUM, pkName == null ? null : PNameFactory.newName(pkName), saltBucketNum, columns.values(),
-                        parent == null ? null : parent.getSchemaName(), parent == null ? null : parent.getTableName(), Collections.<PTable>emptyList(), isImmutableRows,
-                        physicalNames, defaultFamilyName == null ? null : PNameFactory.newName(defaultFamilyName), viewStatement, Boolean.TRUE.equals(disableWAL), multiTenant, storeNulls, viewType,
-                        viewIndexType, result.getViewIndexId(), indexType, rowKeyOrderOptimizable, transactionProvider, updateCacheFrequency, 0L, isNamespaceMapped, autoPartitionSeq, isAppendOnlySchema, immutableStorageScheme, encodingScheme, cqCounterToBe, useStatsForParallelizationProp);
+                PTable table = new PTableImpl.Builder()
+                        .setType(tableType)
+                        .setState(indexState)
+                        .setTimeStamp(timestamp != null ? timestamp : result.getMutationTime())
+                        .setIndexDisableTimestamp(0L)
+                        .setSequenceNumber(PTable.INITIAL_SEQ_NUM)
+                        .setImmutableRows(isImmutableRows)
+                        .setViewStatement(viewStatement)
+                        .setDisableWAL(Boolean.TRUE.equals(disableWAL))
+                        .setMultiTenant(multiTenant)
+                        .setStoreNulls(storeNulls)
+                        .setViewType(viewType)
+                        .setViewIndexType(viewIndexType)
+                        .setViewIndexId(result.getViewIndexId())
+                        .setIndexType(indexType)
+                        .setTransactionProvider(transactionProvider)
+                        .setUpdateCacheFrequency(updateCacheFrequency)
+                        .setNamespaceMapped(isNamespaceMapped)
+                        .setAutoPartitionSeqName(autoPartitionSeq)
+                        .setAppendOnlySchema(isAppendOnlySchema)
+                        .setImmutableStorageScheme(immutableStorageScheme == null ?
+                                ImmutableStorageScheme.ONE_CELL_PER_COLUMN : immutableStorageScheme)
+                        .setQualifierEncodingScheme(encodingScheme == null ?
+                                QualifierEncodingScheme.NON_ENCODED_QUALIFIERS : encodingScheme)
+                        .setBaseColumnCount(QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT)
+                        .setEncodedCQCounter(cqCounterToBe)
+                        .setUseStatsForParallelization(useStatsForParallelizationProp)
+                        .setExcludedColumns(ImmutableList.<PColumn>of())
+                        .setTenantId(tenantId)
+                        .setSchemaName(newSchemaName)
+                        .setTableName(PNameFactory.newName(tableName))
+                        .setPkName(pkName == null ? null : PNameFactory.newName(pkName))
+                        .setDefaultFamilyName(defaultFamilyName == null ?
+                                null : PNameFactory.newName(defaultFamilyName))
+                        .setRowKeyOrderOptimizable(rowKeyOrderOptimizable)
+                        .setBucketNum(saltBucketNum)
+                        .setIndexes(Collections.<PTable>emptyList())
+                        .setParentSchemaName((parent == null) ? null : parent.getSchemaName())
+                        .setParentTableName((parent == null) ? null : parent.getTableName())
+                        .setPhysicalNames(physicalNames == null ?
+                                ImmutableList.<PName>of() : ImmutableList.copyOf(physicalNames))
+                        .setColumns(columns.values())
+                        .build();
                 result = new MetaDataMutationResult(code, result.getMutationTime(), table, true);
                 addTableToCache(result);
                 return table;
@@ -3131,10 +3207,29 @@ public class MetaDataClient {
                                 && (table.isMultiTenant() || hasViewIndexTable)) {
                             if (hasViewIndexTable) {
                                 byte[] viewIndexPhysicalName = MetaDataUtil.getViewIndexPhysicalName(table.getPhysicalName().getBytes());
-                                PTable viewIndexTable = new PTableImpl(null,
-                                        SchemaUtil.getSchemaNameFromFullName(viewIndexPhysicalName),
-                                        SchemaUtil.getTableNameFromFullName(viewIndexPhysicalName), ts,
-                                        table.getColumnFamilies(),table.isNamespaceMapped(), table.getImmutableStorageScheme(), table.getEncodingScheme(), table.useStatsForParallelization());
+                                String viewIndexSchemaName = SchemaUtil.getSchemaNameFromFullName(viewIndexPhysicalName);
+                                String viewIndexTableName = SchemaUtil.getTableNameFromFullName(viewIndexPhysicalName);
+                                PName viewIndexName = PNameFactory.newName(SchemaUtil.getTableName(viewIndexSchemaName, viewIndexTableName));
+
+                                PTable viewIndexTable = new PTableImpl.Builder()
+                                        .setName(viewIndexName)
+                                        .setKey(new PTableKey(tenantId, viewIndexName.getString()))
+                                        .setSchemaName(PNameFactory.newName(viewIndexSchemaName))
+                                        .setTableName(PNameFactory.newName(viewIndexTableName))
+                                        .setType(PTableType.VIEW)
+                                        .setViewType(ViewType.MAPPED)
+                                        .setTimeStamp(ts)
+                                        .setPkColumns(Collections.<PColumn>emptyList())
+                                        .setAllColumns(Collections.<PColumn>emptyList())
+                                        .setRowKeySchema(RowKeySchema.EMPTY_SCHEMA)
+                                        .setIndexes(Collections.<PTable>emptyList())
+                                        .setFamilyAttributes(table.getColumnFamilies())
+                                        .setPhysicalNames(Collections.<PName>emptyList())
+                                        .setNamespaceMapped(table.isNamespaceMapped())
+                                        .setImmutableStorageScheme(table.getImmutableStorageScheme())
+                                        .setQualifierEncodingScheme(table.getEncodingScheme())
+                                        .setUseStatsForParallelization(table.useStatsForParallelization())
+                                        .build();
                                 tableRefs.add(new TableRef(null, viewIndexTable, ts, false));
                             }
                         }
@@ -3754,13 +3849,32 @@ public class MetaDataClient {
                             long ts = (scn == null ? result.getMutationTime() : scn);
                             byte[] viewIndexPhysicalName = MetaDataUtil
                                     .getViewIndexPhysicalName(table.getPhysicalName().getBytes());
-                            PTable viewIndexTable = new PTableImpl(null,
-                                    SchemaUtil.getSchemaNameFromFullName(viewIndexPhysicalName),
-                                    SchemaUtil.getTableNameFromFullName(viewIndexPhysicalName), ts,
-                                    table.getColumnFamilies(), table.isNamespaceMapped(), table.getImmutableStorageScheme(), table.getEncodingScheme(), table.useStatsForParallelization());
+                            String viewIndexSchemaName = SchemaUtil.getSchemaNameFromFullName(viewIndexPhysicalName);
+                            String viewIndexTableName = SchemaUtil.getTableNameFromFullName(viewIndexPhysicalName);
+                            PName viewIndexName = PNameFactory.newName(SchemaUtil.getTableName(viewIndexSchemaName, viewIndexTableName));
+
+                            PTable viewIndexTable = new PTableImpl.Builder()
+                                    .setName(viewIndexName)
+                                    .setKey(new PTableKey(tenantId, viewIndexName.getString()))
+                                    .setSchemaName(PNameFactory.newName(viewIndexSchemaName))
+                                    .setTableName(PNameFactory.newName(viewIndexTableName))
+                                    .setType(PTableType.VIEW)
+                                    .setViewType(ViewType.MAPPED)
+                                    .setTimeStamp(ts)
+                                    .setPkColumns(Collections.<PColumn>emptyList())
+                                    .setAllColumns(Collections.<PColumn>emptyList())
+                                    .setRowKeySchema(RowKeySchema.EMPTY_SCHEMA)
+                                    .setIndexes(Collections.<PTable>emptyList())
+                                    .setFamilyAttributes(table.getColumnFamilies())
+                                    .setPhysicalNames(Collections.<PName>emptyList())
+                                    .setNamespaceMapped(table.isNamespaceMapped())
+                                    .setImmutableStorageScheme(table.getImmutableStorageScheme())
+                                    .setQualifierEncodingScheme(table.getEncodingScheme())
+                                    .setUseStatsForParallelization(table.useStatsForParallelization())
+                                    .build();
                             List<TableRef> tableRefs = Collections.singletonList(new TableRef(null, viewIndexTable, ts, false));
                             MutationPlan plan = new PostDDLCompiler(connection).compile(tableRefs, null, null,
-                                    Collections.<PColumn> emptyList(), ts);
+                                    Collections.<PColumn>emptyList(), ts);
                             connection.getQueryServices().updateData(plan);
                         }
                     }
@@ -4029,21 +4143,44 @@ public class MetaDataClient {
                         Map<String, List<TableRef>> tenantIdTableRefMap = Maps.newHashMap();
                         if (result.getSharedTablesToDelete() != null) {
                             for (SharedTableState sharedTableState : result.getSharedTablesToDelete()) {
-                                PTableImpl viewIndexTable =
-                                        new PTableImpl(sharedTableState.getTenantId(),
-                                                sharedTableState.getSchemaName(),
-                                                sharedTableState.getTableName(), ts,
-                                                table.getColumnFamilies(),
-                                                sharedTableState.getColumns(),
-                                                sharedTableState.getPhysicalNames(),
-                                                sharedTableState.getViewIndexType(),
-                                                sharedTableState.getViewIndexId(),
-                                                table.isMultiTenant(), table.isNamespaceMapped(),
-                                                table.getImmutableStorageScheme(),
-                                                table.getEncodingScheme(),
-                                                table.getEncodedCQCounter(),
-                                                table.useStatsForParallelization(),
-                                                table.getBucketNum());
+                                ImmutableStorageScheme storageScheme = table.getImmutableStorageScheme();
+                                QualifierEncodingScheme qualifierEncodingScheme = table.getEncodingScheme();
+                                List<PColumn> columns = sharedTableState.getColumns();
+                                if (table.getBucketNum() != null) {
+                                    columns = columns.subList(1, columns.size());
+                                }
+
+                                PTableImpl viewIndexTable = new PTableImpl.Builder()
+                                        .setPkColumns(Collections.<PColumn>emptyList())
+                                        .setAllColumns(Collections.<PColumn>emptyList())
+                                        .setRowKeySchema(RowKeySchema.EMPTY_SCHEMA)
+                                        .setIndexes(Collections.<PTable>emptyList())
+                                        .setFamilyAttributes(table.getColumnFamilies())
+                                        .setType(PTableType.INDEX)
+                                        .setTimeStamp(ts)
+                                        .setMultiTenant(table.isMultiTenant())
+                                        .setViewIndexType(sharedTableState.getViewIndexType())
+                                        .setViewIndexId(sharedTableState.getViewIndexId())
+                                        .setNamespaceMapped(table.isNamespaceMapped())
+                                        .setAppendOnlySchema(false)
+                                        .setImmutableStorageScheme(storageScheme == null ?
+                                                ImmutableStorageScheme.ONE_CELL_PER_COLUMN : storageScheme)
+                                        .setQualifierEncodingScheme(qualifierEncodingScheme == null ?
+                                                QualifierEncodingScheme.NON_ENCODED_QUALIFIERS : qualifierEncodingScheme)
+                                        .setEncodedCQCounter(table.getEncodedCQCounter())
+                                        .setUseStatsForParallelization(table.useStatsForParallelization())
+                                        .setExcludedColumns(ImmutableList.<PColumn>of())
+                                        .setTenantId(sharedTableState.getTenantId())
+                                        .setSchemaName(sharedTableState.getSchemaName())
+                                        .setTableName(sharedTableState.getTableName())
+                                        .setRowKeyOrderOptimizable(false)
+                                        .setBucketNum(table.getBucketNum())
+                                        .setIndexes(Collections.<PTable>emptyList())
+                                        .setPhysicalNames(sharedTableState.getPhysicalNames() == null ?
+                                                ImmutableList.<PName>of() :
+                                                ImmutableList.copyOf(sharedTableState.getPhysicalNames()))
+                                        .setColumns(columns)
+                                        .build();
                                 TableRef indexTableRef = new TableRef(viewIndexTable);
                                 PName indexTableTenantId = sharedTableState.getTenantId();
                                 if (indexTableTenantId==null) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/02a6bbce/phoenix-core/src/main/java/org/apache/phoenix/schema/PMetaDataImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/PMetaDataImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/PMetaDataImpl.java
index 598cc79..3ce70ea 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/PMetaDataImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/PMetaDataImpl.java
@@ -17,7 +17,10 @@
  */
 package org.apache.phoenix.schema;
 
+import static org.apache.phoenix.schema.PTableImpl.getColumnsToClone;
+
 import java.sql.SQLException;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 
@@ -27,7 +30,6 @@ import org.apache.phoenix.parse.PSchema;
 import org.apache.phoenix.query.QueryServices;
 import org.apache.phoenix.query.QueryServicesOptions;
 import org.apache.phoenix.util.ReadOnlyProps;
-import org.apache.phoenix.util.SchemaUtil;
 import org.apache.phoenix.util.TimeKeeper;
 
 import com.google.common.collect.Lists;
@@ -121,7 +123,11 @@ public class PMetaDataImpl implements PMetaData {
                 }
                 newIndexes.add(table);
                 netGain -= oldParentRef.getEstimatedSize();
-                newParentTable = PTableImpl.makePTable(oldParentRef.getTable(), table.getTimeStamp(), newIndexes);
+                newParentTable = PTableImpl.builderWithColumns(oldParentRef.getTable(),
+                        getColumnsToClone(oldParentRef.getTable()))
+                        .setIndexes(newIndexes)
+                        .setTimeStamp(table.getTimeStamp())
+                        .build();
                 newParentTableRef = tableRefFactory.makePTableRef(newParentTable, this.timeKeeper.getCurrentTime(), parentResolvedTimestamp);
                 netGain += newParentTableRef.getEstimatedSize();
             }
@@ -173,10 +179,14 @@ public class PMetaDataImpl implements PMetaData {
                     PTable index = newIndexes.get(i);
                     if (index.getName().getString().equals(tableName)) {
                         newIndexes.remove(i);
-                        PTable parentTable = PTableImpl.makePTable(
-                                parentTableRef.getTable(),
-                                tableTimeStamp == HConstants.LATEST_TIMESTAMP ? parentTableRef.getTable().getTimeStamp() : tableTimeStamp,
-                                newIndexes);
+                        PTableImpl.Builder parentTableBuilder =
+                                PTableImpl.builderWithColumns(parentTableRef.getTable(),
+                                        getColumnsToClone(parentTableRef.getTable()))
+                                .setIndexes(newIndexes == null ? Collections.<PTable>emptyList() : newIndexes);
+                        if (tableTimeStamp != HConstants.LATEST_TIMESTAMP) {
+                            parentTableBuilder.setTimeStamp(tableTimeStamp);
+                        }
+                        PTable parentTable = parentTableBuilder.build();
                         metaData.put(parentTable.getKey(), tableRefFactory.makePTableRef(parentTable, this.timeKeeper.getCurrentTime(), parentTableRef.getResolvedTimeStamp()));
                         break;
                     }
@@ -218,8 +228,10 @@ public class PMetaDataImpl implements PMetaData {
                     oldColumn.getTimestamp());
                 columns.add(newColumn);
             }
-            
-            table = PTableImpl.makePTable(table, tableTimeStamp, tableSeqNum, columns);
+            table = PTableImpl.builderWithColumns(table, columns)
+                    .setTimeStamp(tableTimeStamp)
+                    .setSequenceNumber(tableSeqNum)
+                    .build();
         }
         tables.put(table.getKey(), tableRefFactory.makePTableRef(table, this.timeKeeper.getCurrentTime(), resolvedTime));
     }