use of org.apache.phoenix.schema.SortOrder in project phoenix by apache.
the class IndexMaintainer method buildUpdateMutation.
public Put buildUpdateMutation(KeyValueBuilder kvBuilder, ValueGetter valueGetter, ImmutableBytesWritable dataRowKeyPtr, long ts, byte[] regionStartKey, byte[] regionEndKey) throws IOException {
byte[] indexRowKey = this.buildRowKey(valueGetter, dataRowKeyPtr, regionStartKey, regionEndKey);
Put put = null;
// New row being inserted: add the empty key value
if (valueGetter == null || valueGetter.getLatestValue(dataEmptyKeyValueRef) == null) {
put = new Put(indexRowKey);
// add the keyvalue for the empty row
put.add(kvBuilder.buildPut(new ImmutableBytesPtr(indexRowKey), this.getEmptyKeyValueFamily(), dataEmptyKeyValueRef.getQualifierWritable(), ts, // set the value to the empty column name
dataEmptyKeyValueRef.getQualifierWritable()));
put.setDurability(!indexWALDisabled ? Durability.USE_DEFAULT : Durability.SKIP_WAL);
}
ImmutableBytesPtr rowKey = new ImmutableBytesPtr(indexRowKey);
if (immutableStorageScheme != ImmutableStorageScheme.ONE_CELL_PER_COLUMN) {
// map from index column family to list of pair of index column and data column (for covered columns)
Map<ImmutableBytesPtr, List<Pair<ColumnReference, ColumnReference>>> familyToColListMap = Maps.newHashMap();
for (ColumnReference ref : this.getCoveredColumns()) {
ColumnReference indexColRef = this.coveredColumnsMap.get(ref);
ImmutableBytesPtr cf = new ImmutableBytesPtr(indexColRef.getFamily());
if (!familyToColListMap.containsKey(cf)) {
familyToColListMap.put(cf, Lists.<Pair<ColumnReference, ColumnReference>>newArrayList());
}
familyToColListMap.get(cf).add(Pair.newPair(indexColRef, ref));
}
// iterate over each column family and create a byte[] containing all the columns
for (Entry<ImmutableBytesPtr, List<Pair<ColumnReference, ColumnReference>>> entry : familyToColListMap.entrySet()) {
byte[] columnFamily = entry.getKey().copyBytesIfNecessary();
List<Pair<ColumnReference, ColumnReference>> colRefPairs = entry.getValue();
int maxEncodedColumnQualifier = Integer.MIN_VALUE;
// find the max col qualifier
for (Pair<ColumnReference, ColumnReference> colRefPair : colRefPairs) {
maxEncodedColumnQualifier = Math.max(maxEncodedColumnQualifier, encodingScheme.decode(colRefPair.getFirst().getQualifier()));
}
Expression[] colValues = EncodedColumnsUtil.createColumnExpressionArray(maxEncodedColumnQualifier);
// set the values of the columns
for (Pair<ColumnReference, ColumnReference> colRefPair : colRefPairs) {
ColumnReference indexColRef = colRefPair.getFirst();
ColumnReference dataColRef = colRefPair.getSecond();
Expression expression = new SingleCellColumnExpression(new PDatum() {
@Override
public boolean isNullable() {
return false;
}
@Override
public SortOrder getSortOrder() {
return null;
}
@Override
public Integer getScale() {
return null;
}
@Override
public Integer getMaxLength() {
return null;
}
@Override
public PDataType getDataType() {
return null;
}
}, dataColRef.getFamily(), dataColRef.getQualifier(), encodingScheme);
ImmutableBytesPtr ptr = new ImmutableBytesPtr();
expression.evaluate(new ValueGetterTuple(valueGetter), ptr);
byte[] value = ptr.copyBytesIfNecessary();
if (value != null) {
int indexArrayPos = encodingScheme.decode(indexColRef.getQualifier()) - QueryConstants.ENCODED_CQ_COUNTER_INITIAL_VALUE + 1;
colValues[indexArrayPos] = new LiteralExpression(value);
}
}
List<Expression> children = Arrays.asList(colValues);
// we use SingleCellConstructorExpression to serialize multiple columns into a single byte[]
SingleCellConstructorExpression singleCellConstructorExpression = new SingleCellConstructorExpression(immutableStorageScheme, children);
ImmutableBytesWritable ptr = new ImmutableBytesWritable();
singleCellConstructorExpression.evaluate(new BaseTuple() {
}, ptr);
if (put == null) {
put = new Put(indexRowKey);
put.setDurability(!indexWALDisabled ? Durability.USE_DEFAULT : Durability.SKIP_WAL);
}
ImmutableBytesPtr colFamilyPtr = new ImmutableBytesPtr(columnFamily);
//this is a little bit of extra work for installations that are running <0.94.14, but that should be rare and is a short-term set of wrappers - it shouldn't kill GC
put.add(kvBuilder.buildPut(rowKey, colFamilyPtr, QueryConstants.SINGLE_KEYVALUE_COLUMN_QUALIFIER_BYTES_PTR, ts, ptr));
}
} else {
for (ColumnReference ref : this.getCoveredColumns()) {
ColumnReference indexColRef = this.coveredColumnsMap.get(ref);
ImmutableBytesPtr cq = indexColRef.getQualifierWritable();
ImmutableBytesPtr cf = indexColRef.getFamilyWritable();
ImmutableBytesWritable value = valueGetter.getLatestValue(ref);
if (value != null) {
if (put == null) {
put = new Put(indexRowKey);
put.setDurability(!indexWALDisabled ? Durability.USE_DEFAULT : Durability.SKIP_WAL);
}
put.add(kvBuilder.buildPut(rowKey, cf, cq, ts, value));
}
}
}
return put;
}
use of org.apache.phoenix.schema.SortOrder in project phoenix by apache.
the class IndexMaintainer method generateIndexRowKeySchema.
// We have enough information to generate the index row key schema
private RowKeySchema generateIndexRowKeySchema() {
int nIndexedColumns = getIndexPkColumnCount() + (isMultiTenant ? 1 : 0) + (!isLocalIndex && nIndexSaltBuckets > 0 ? 1 : 0) + (viewIndexId != null ? 1 : 0) - getNumViewConstants();
RowKeySchema.RowKeySchemaBuilder builder = new RowKeySchema.RowKeySchemaBuilder(nIndexedColumns);
builder.rowKeyOrderOptimizable(rowKeyOrderOptimizable);
if (!isLocalIndex && nIndexSaltBuckets > 0) {
builder.addField(SaltingUtil.SALTING_COLUMN, false, SortOrder.ASC);
nIndexedColumns--;
}
int dataPosOffset = isDataTableSalted ? 1 : 0;
if (viewIndexId != null) {
nIndexedColumns--;
builder.addField(new PDatum() {
@Override
public boolean isNullable() {
return false;
}
@Override
public PDataType getDataType() {
return MetaDataUtil.getViewIndexIdDataType();
}
@Override
public Integer getMaxLength() {
return null;
}
@Override
public Integer getScale() {
return null;
}
@Override
public SortOrder getSortOrder() {
return SortOrder.getDefault();
}
}, false, SortOrder.getDefault());
}
if (isMultiTenant) {
Field field = dataRowKeySchema.getField(dataPosOffset++);
builder.addField(field, field.isNullable(), field.getSortOrder());
nIndexedColumns--;
}
Field[] indexFields = new Field[nIndexedColumns];
BitSet viewConstantColumnBitSet = this.rowKeyMetaData.getViewConstantColumnBitSet();
// Add Field for all data row pk columns
for (int i = dataPosOffset; i < dataRowKeySchema.getFieldCount(); i++) {
// same for all rows in this index)
if (!viewConstantColumnBitSet.get(i)) {
int pos = rowKeyMetaData.getIndexPkPosition(i - dataPosOffset);
indexFields[pos] = dataRowKeySchema.getField(i);
}
}
BitSet descIndexColumnBitSet = rowKeyMetaData.getDescIndexColumnBitSet();
Iterator<Expression> expressionItr = indexedExpressions.iterator();
for (int i = 0; i < indexFields.length; i++) {
Field indexField = indexFields[i];
PDataType dataTypeToBe;
SortOrder sortOrderToBe;
boolean isNullableToBe;
Integer maxLengthToBe;
Integer scaleToBe;
if (indexField == null) {
Expression e = expressionItr.next();
isNullableToBe = e.isNullable();
dataTypeToBe = IndexUtil.getIndexColumnDataType(isNullableToBe, e.getDataType());
sortOrderToBe = descIndexColumnBitSet.get(i) ? SortOrder.DESC : SortOrder.ASC;
maxLengthToBe = e.getMaxLength();
scaleToBe = e.getScale();
} else {
isNullableToBe = indexField.isNullable();
dataTypeToBe = IndexUtil.getIndexColumnDataType(isNullableToBe, indexField.getDataType());
sortOrderToBe = descIndexColumnBitSet.get(i) ? SortOrder.DESC : SortOrder.ASC;
maxLengthToBe = indexField.getMaxLength();
scaleToBe = indexField.getScale();
}
final PDataType dataType = dataTypeToBe;
final SortOrder sortOrder = sortOrderToBe;
final boolean isNullable = isNullableToBe;
final Integer maxLength = maxLengthToBe;
final Integer scale = scaleToBe;
builder.addField(new PDatum() {
@Override
public boolean isNullable() {
return isNullable;
}
@Override
public PDataType getDataType() {
return dataType;
}
@Override
public Integer getMaxLength() {
return maxLength;
}
@Override
public Integer getScale() {
return scale;
}
@Override
public SortOrder getSortOrder() {
return sortOrder;
}
}, true, sortOrder);
}
return builder.build();
}
use of org.apache.phoenix.schema.SortOrder in project phoenix by apache.
the class SkipScanFilterIntersectTest method foreach.
private static Collection<?> foreach(KeyRange[][] ranges, int[] widths, byte[] lowerInclusive, byte[] upperExclusive, KeyRange[][] expectedRanges) {
List<List<KeyRange>> slots = Lists.transform(Lists.newArrayList(ranges), ARRAY_TO_LIST);
List<List<KeyRange>> expectedSlots = expectedRanges == null ? null : Lists.transform(Lists.newArrayList(expectedRanges), ARRAY_TO_LIST);
RowKeySchemaBuilder builder = new RowKeySchemaBuilder(10);
for (final int width : widths) {
builder.addField(new PDatum() {
@Override
public boolean isNullable() {
return width <= 0;
}
@Override
public PDataType getDataType() {
return width <= 0 ? PVarchar.INSTANCE : PChar.INSTANCE;
}
@Override
public Integer getMaxLength() {
return width <= 0 ? null : width;
}
@Override
public Integer getScale() {
return null;
}
@Override
public SortOrder getSortOrder() {
return SortOrder.getDefault();
}
}, width <= 0, SortOrder.getDefault());
}
List<Object> ret = Lists.newArrayList();
ret.add(new Object[] { slots, builder.build(), lowerInclusive, upperExclusive, expectedSlots });
return ret;
}
use of org.apache.phoenix.schema.SortOrder in project phoenix by apache.
the class ExpressionCompiler method visitLeave.
@Override
public Expression visitLeave(SubtractParseNode node, List<Expression> children) throws SQLException {
return visitLeave(node, children, new ArithmeticExpressionBinder() {
@Override
public PDatum getBindMetaData(int i, List<Expression> children, final Expression expression) {
final PDataType type;
// we know that the first parameter must be a date type too.
if (i == 0 && (type = children.get(1).getDataType()) != null && type.isCoercibleTo(PDate.INSTANCE)) {
return new PDatum() {
@Override
public boolean isNullable() {
return expression.isNullable();
}
@Override
public PDataType getDataType() {
return type;
}
@Override
public Integer getMaxLength() {
return expression.getMaxLength();
}
@Override
public Integer getScale() {
return expression.getScale();
}
@Override
public SortOrder getSortOrder() {
return expression.getSortOrder();
}
};
} else if (expression.getDataType() != null && expression.getDataType().isCoercibleTo(PDate.INSTANCE)) {
return new // Same as with addition
PDatum() {
@Override
public boolean isNullable() {
return expression.isNullable();
}
@Override
public PDataType getDataType() {
return PDecimal.INSTANCE;
}
@Override
public Integer getMaxLength() {
return expression.getMaxLength();
}
@Override
public Integer getScale() {
return expression.getScale();
}
@Override
public SortOrder getSortOrder() {
return expression.getSortOrder();
}
};
}
// Otherwise just go with what was calculated for the expression
return expression;
}
}, new ArithmeticExpressionFactory() {
@Override
public Expression create(ArithmeticParseNode node, List<Expression> children) throws SQLException {
int i = 0;
PDataType theType = null;
Expression e1 = children.get(0);
Expression e2 = children.get(1);
Determinism determinism = e1.getDeterminism().combine(e2.getDeterminism());
PDataType type1 = e1.getDataType();
PDataType type2 = e2.getDataType();
// TODO: simplify this special case for DATE conversion
/**
* For date1-date2, we want to coerce to a LONG because this
* cannot be compared against another date. It has essentially
* become a number. For date1-5, we want to preserve the DATE
* type because this can still be compared against another date
* and cannot be multiplied or divided. Any other time occurs is
* an error. For example, 5-date1 is an error. The nulls occur if
* we have bind variables.
*/
boolean isType1Date = type1 != null && type1 != PTimestamp.INSTANCE && type1 != PUnsignedTimestamp.INSTANCE && type1.isCoercibleTo(PDate.INSTANCE);
boolean isType2Date = type2 != null && type2 != PTimestamp.INSTANCE && type2 != PUnsignedTimestamp.INSTANCE && type2.isCoercibleTo(PDate.INSTANCE);
if (isType1Date || isType2Date) {
if (isType1Date && isType2Date) {
i = 2;
theType = PDecimal.INSTANCE;
} else if (isType1Date && type2 != null && type2.isCoercibleTo(PDecimal.INSTANCE)) {
i = 2;
theType = PDate.INSTANCE;
} else if (type1 == null || type2 == null) {
/*
* FIXME: Could be either a Date or BigDecimal, but we
* don't know if we're comparing to a date or a number
* which would be disambiguate it.
*/
i = 2;
theType = null;
}
} else if (type1 == PTimestamp.INSTANCE || type2 == PTimestamp.INSTANCE) {
i = 2;
theType = PTimestamp.INSTANCE;
} else if (type1 == PUnsignedTimestamp.INSTANCE || type2 == PUnsignedTimestamp.INSTANCE) {
i = 2;
theType = PUnsignedTimestamp.INSTANCE;
}
for (; i < children.size(); i++) {
// This logic finds the common type to which all child types are coercible
// without losing precision.
Expression e = children.get(i);
determinism = determinism.combine(e.getDeterminism());
PDataType type = e.getDataType();
if (type == null) {
continue;
} else if (type.isCoercibleTo(PLong.INSTANCE)) {
if (theType == null) {
theType = PLong.INSTANCE;
}
} else if (type == PDecimal.INSTANCE) {
// unless we're doing date arithmetic.
if (theType == null || !theType.isCoercibleTo(PDate.INSTANCE)) {
theType = PDecimal.INSTANCE;
}
} else if (type.isCoercibleTo(PDouble.INSTANCE)) {
// unless we're doing date arithmetic or we've found another child of type DECIMAL
if (theType == null || (theType != PDecimal.INSTANCE && !theType.isCoercibleTo(PDate.INSTANCE))) {
theType = PDouble.INSTANCE;
}
} else {
throw TypeMismatchException.newException(type, node.toString());
}
}
if (theType == PDecimal.INSTANCE) {
return new DecimalSubtractExpression(children);
} else if (theType == PLong.INSTANCE) {
return new LongSubtractExpression(children);
} else if (theType == PDouble.INSTANCE) {
return new DoubleSubtractExpression(children);
} else if (theType == null) {
return LiteralExpression.newConstant(null, theType, determinism);
} else if (theType == PTimestamp.INSTANCE || theType == PUnsignedTimestamp.INSTANCE) {
return new TimestampSubtractExpression(children);
} else if (theType.isCoercibleTo(PDate.INSTANCE)) {
return new DateSubtractExpression(children);
} else {
throw TypeMismatchException.newException(theType, node.toString());
}
}
});
}
use of org.apache.phoenix.schema.SortOrder in project phoenix by apache.
the class OrderPreservingTracker method track.
public void track(Expression node) {
SortOrder sortOrder = node.getSortOrder();
track(node, sortOrder, null);
}
Aggregations