| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.phoenix.schema; |
| |
| import org.apache.hadoop.hbase.util.ByteStringer; |
| import org.apache.phoenix.coprocessor.generated.PTableProtos; |
| import org.apache.phoenix.query.QueryConstants; |
| import org.apache.phoenix.schema.types.PDataType; |
| import org.apache.phoenix.util.SchemaUtil; |
| import org.apache.phoenix.util.SizedUtil; |
| |
| import com.google.common.base.Preconditions; |
| |
| public class PColumnImpl implements PColumn { |
| private PName name; |
| private PName familyName; |
| private PDataType dataType; |
| private Integer maxLength; |
| private Integer scale; |
| private boolean nullable; |
| private int position; |
| private SortOrder sortOrder; |
| private Integer arraySize; |
| private byte[] viewConstant; |
| private boolean isViewReferenced; |
| private String expressionStr; |
| private boolean isRowTimestamp; |
| private boolean isDynamic; |
| private byte[] columnQualifierBytes; |
| |
| public PColumnImpl() { |
| } |
| |
| public PColumnImpl(PName name, |
| PName familyName, |
| PDataType dataType, |
| Integer maxLength, |
| Integer scale, |
| boolean nullable, |
| int position, |
| SortOrder sortOrder, Integer arrSize, byte[] viewConstant, boolean isViewReferenced, String expressionStr, boolean isRowTimestamp, boolean isDynamic, byte[] columnQualifierBytes) { |
| init(name, familyName, dataType, maxLength, scale, nullable, position, sortOrder, arrSize, viewConstant, isViewReferenced, expressionStr, isRowTimestamp, isDynamic, columnQualifierBytes); |
| } |
| |
| public PColumnImpl(PColumn column, int position) { |
| this(column.getName(), column.getFamilyName(), column.getDataType(), column.getMaxLength(), |
| column.getScale(), column.isNullable(), position, column.getSortOrder(), column.getArraySize(), column.getViewConstant(), column.isViewReferenced(), column.getExpressionStr(), column.isRowTimestamp(), column.isDynamic(), column.getColumnQualifierBytes()); |
| } |
| |
| private void init(PName name, |
| PName familyName, |
| PDataType dataType, |
| Integer maxLength, |
| Integer scale, |
| boolean nullable, |
| int position, |
| SortOrder sortOrder, |
| Integer arrSize, |
| byte[] viewConstant, boolean isViewReferenced, String expressionStr, boolean isRowTimestamp, boolean isDynamic, byte[] columnQualifierBytes) { |
| Preconditions.checkNotNull(sortOrder); |
| this.dataType = dataType; |
| if (familyName == null) { |
| // Allow nullable columns in PK, but only if they're variable length. |
| // Variable length types may be null, since we use a null-byte terminator |
| // (which is a disallowed character in variable length types). However, |
| // fixed width types do not have a way of representing null. |
| // TODO: we may be able to allow this for columns at the end of the PK |
| Preconditions.checkArgument(!nullable || !dataType.isFixedWidth(), |
| "PK columns may not be both fixed width and nullable: " + name.getString()); |
| } |
| this.name = name; |
| this.familyName = familyName == null ? null : familyName; |
| this.maxLength = maxLength; |
| this.scale = scale; |
| this.nullable = nullable; |
| this.position = position; |
| this.sortOrder = sortOrder; |
| this.arraySize = arrSize; |
| this.viewConstant = viewConstant; |
| this.isViewReferenced = isViewReferenced; |
| this.expressionStr = expressionStr; |
| this.isRowTimestamp = isRowTimestamp; |
| this.isDynamic = isDynamic; |
| this.columnQualifierBytes = columnQualifierBytes; |
| } |
| |
| @Override |
| public int getEstimatedSize() { |
| return SizedUtil.OBJECT_SIZE + SizedUtil.POINTER_SIZE * 8 + SizedUtil.INT_OBJECT_SIZE * 3 + SizedUtil.INT_SIZE + |
| name.getEstimatedSize() + (familyName == null ? 0 : familyName.getEstimatedSize()) + |
| (viewConstant == null ? 0 : (SizedUtil.ARRAY_SIZE + viewConstant.length)); |
| } |
| |
| @Override |
| public PName getName() { |
| return name; |
| } |
| |
| @Override |
| public PName getFamilyName() { |
| return familyName; |
| } |
| |
| @Override |
| public PDataType getDataType() { |
| return dataType; |
| } |
| |
| @Override |
| public Integer getMaxLength() { |
| return maxLength; |
| } |
| |
| @Override |
| public Integer getScale() { |
| return scale; |
| } |
| |
| @Override |
| public String getExpressionStr() { |
| return expressionStr; |
| } |
| |
| @Override |
| public boolean isNullable() { |
| // Only PK columns can be NOT NULL. We prevent this in the |
| // CREATE TABLE statement now (PHOENIX-1266), but this extra |
| // check for familyName != null will ensure that for existing |
| // tables we never treat key value columns as NOT NULL. |
| return nullable || familyName != null; |
| } |
| |
| @Override |
| public int getPosition() { |
| return position; |
| } |
| |
| @Override |
| public SortOrder getSortOrder() { |
| return sortOrder; |
| } |
| |
| @Override |
| public String toString() { |
| return (familyName == null ? "" : familyName.toString() + QueryConstants.NAME_SEPARATOR) + name.toString(); |
| } |
| |
| @Override |
| public int hashCode() { |
| final int prime = 31; |
| int result = 1; |
| result = prime * result + ((familyName == null) ? 0 : familyName.hashCode()); |
| result = prime * result + ((name == null) ? 0 : name.hashCode()); |
| return result; |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) return true; |
| if (obj == null) return false; |
| if (! (obj instanceof PColumn) ) return false; |
| PColumn other = (PColumn)obj; |
| if (familyName == null) { |
| if (other.getFamilyName() != null) return false; |
| } else if (!familyName.equals(other.getFamilyName())) return false; |
| if (name == null) { |
| if (other.getName() != null) return false; |
| } else if (!name.equals(other.getName())) return false; |
| return true; |
| } |
| |
| @Override |
| public Integer getArraySize() { |
| return arraySize; |
| } |
| |
| @Override |
| public byte[] getViewConstant() { |
| return viewConstant; |
| } |
| |
| @Override |
| public boolean isViewReferenced() { |
| return isViewReferenced; |
| } |
| |
| @Override |
| public boolean isRowTimestamp() { |
| return isRowTimestamp; |
| } |
| |
| @Override |
| public boolean isDynamic() { |
| return isDynamic; |
| } |
| |
| @Override |
| public byte[] getColumnQualifierBytes() { |
| // Needed for backward compatibility |
| if (!SchemaUtil.isPKColumn(this) && columnQualifierBytes == null) { |
| return this.name.getBytes(); |
| } |
| return columnQualifierBytes; |
| } |
| |
| /** |
| * Create a PColumn instance from PBed PColumn instance |
| * |
| * @param column |
| */ |
| public static PColumn createFromProto(PTableProtos.PColumn column) { |
| byte[] columnNameBytes = column.getColumnNameBytes().toByteArray(); |
| PName columnName = PNameFactory.newName(columnNameBytes); |
| PName familyName = null; |
| if (column.hasFamilyNameBytes()) { |
| familyName = PNameFactory.newName(column.getFamilyNameBytes().toByteArray()); |
| } |
| PDataType dataType = PDataType.fromSqlTypeName(column.getDataType()); |
| Integer maxLength = null; |
| if (column.hasMaxLength()) { |
| maxLength = column.getMaxLength(); |
| } |
| Integer scale = null; |
| if (column.hasScale()) { |
| scale = column.getScale(); |
| } |
| boolean nullable = column.getNullable(); |
| int position = column.getPosition(); |
| SortOrder sortOrder = SortOrder.fromSystemValue(column.getSortOrder()); |
| Integer arraySize = null; |
| if (column.hasArraySize()) { |
| arraySize = column.getArraySize(); |
| } |
| byte[] viewConstant = null; |
| if (column.hasViewConstant()) { |
| viewConstant = column.getViewConstant().toByteArray(); |
| } |
| boolean isViewReferenced = false; |
| if (column.hasViewReferenced()) { |
| isViewReferenced = column.getViewReferenced(); |
| } |
| String expressionStr = null; |
| if (column.hasExpression()) { |
| expressionStr = column.getExpression(); |
| } |
| boolean isRowTimestamp = column.getIsRowTimestamp(); |
| boolean isDynamic = false; |
| if (column.hasIsDynamic()) { |
| isDynamic = column.getIsDynamic(); |
| } |
| byte[] columnQualifierBytes = null; |
| if (column.hasColumnQualifierBytes()) { |
| columnQualifierBytes = column.getColumnQualifierBytes().toByteArray(); |
| } |
| return new PColumnImpl(columnName, familyName, dataType, maxLength, scale, nullable, position, sortOrder, |
| arraySize, viewConstant, isViewReferenced, expressionStr, isRowTimestamp, isDynamic, columnQualifierBytes); |
| } |
| |
| public static PTableProtos.PColumn toProto(PColumn column) { |
| PTableProtos.PColumn.Builder builder = PTableProtos.PColumn.newBuilder(); |
| builder.setColumnNameBytes(ByteStringer.wrap(column.getName().getBytes())); |
| if (column.getFamilyName() != null) { |
| builder.setFamilyNameBytes(ByteStringer.wrap(column.getFamilyName().getBytes())); |
| } |
| builder.setDataType(column.getDataType().getSqlTypeName()); |
| if (column.getMaxLength() != null) { |
| builder.setMaxLength(column.getMaxLength()); |
| } |
| if (column.getScale() != null) { |
| builder.setScale(column.getScale()); |
| } |
| builder.setNullable(column.isNullable()); |
| builder.setPosition(column.getPosition()); |
| builder.setSortOrder(column.getSortOrder().getSystemValue()); |
| if (column.getArraySize() != null) { |
| builder.setArraySize(column.getArraySize()); |
| } |
| if (column.getViewConstant() != null) { |
| builder.setViewConstant(ByteStringer.wrap(column.getViewConstant())); |
| } |
| builder.setViewReferenced(column.isViewReferenced()); |
| |
| if (column.getExpressionStr() != null) { |
| builder.setExpression(column.getExpressionStr()); |
| } |
| builder.setIsRowTimestamp(column.isRowTimestamp()); |
| if (column.getColumnQualifierBytes() != null) { |
| builder.setColumnQualifierBytes(ByteStringer.wrap(column.getColumnQualifierBytes())); |
| } |
| return builder.build(); |
| } |
| } |