package io.indexr.segment.rc; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import org.apache.spark.unsafe.types.UTF8String; import java.io.IOException; import java.util.Collection; import java.util.Collections; import io.indexr.segment.Column; import io.indexr.segment.ColumnType; import io.indexr.segment.InfoSegment; import io.indexr.segment.OuterIndex; import io.indexr.segment.PackExtIndex; import io.indexr.segment.RSValue; import io.indexr.segment.Segment; import io.indexr.segment.storage.ColumnNode; import io.indexr.util.BitMap; public class Between implements CmpOperator { @JsonProperty("attr") public final Attr attr; @JsonProperty("numValue1") public final long numValue1; @JsonProperty("numValue2") public final long numValue2; @JsonIgnore public final UTF8String strValue1; @JsonIgnore public final UTF8String strValue2; @JsonProperty("strValue1") public String getStrValue1() {return strValue1 == null ? null : strValue1.toString();} @JsonProperty("strValue2") public String getStrValue2() {return strValue2 == null ? null : strValue2.toString();} @JsonCreator public Between(@JsonProperty("attr") Attr attr, @JsonProperty("numValue1") long numValue1, @JsonProperty("numValue2") long numValue2, @JsonProperty("strValue1") String strValue1, @JsonProperty("strValue2") String strValue2) { this(attr, numValue1, numValue2, strValue1 == null ? null : UTF8String.fromString(strValue1), strValue2 == null ? null : UTF8String.fromString(strValue2)); } public Between(Attr attr, long numValue1, long numValue2, UTF8String strValue1, UTF8String strValue2) { this.attr = attr; this.numValue1 = numValue1; this.numValue2 = numValue2; this.strValue1 = strValue1; this.strValue2 = strValue2; } @Override public String getType() {return "between";} @Override public Collection<Attr> attr() { return Collections.singleton(attr); } @Override public RCOperator applyNot() { return new NotBetween(attr, numValue1, numValue2, strValue1, strValue2); } @Override public BitMap exactCheckOnPack(Segment segment) throws IOException { assert attr.checkCurrent(segment.schema().columns); Column column = segment.column(attr.columnId()); try (OuterIndex outerIndex = column.outerIndex()) { return outerIndex.between(column, numValue1, numValue2, strValue1, strValue2, false); } } @Override public byte roughCheckOnPack(Segment segment, int packId) throws IOException { assert attr.checkCurrent(segment.schema().columns); int colId = attr.columnId(); Column column = segment.column(colId); byte type = column.dataType(); if (ColumnType.isNumber(type)) { return RoughCheck_N.betweenCheckOnPack(column, packId, numValue1, numValue2); } else { return RSValue.Some; } } @Override public byte roughCheckOnColumn(InfoSegment segment) throws IOException { assert attr.checkCurrent(segment.schema().columns); int colId = attr.columnId(); ColumnNode columnNode = segment.columnNode(colId); byte type = attr.dataType(); if (ColumnType.isNumber(type)) { return RoughCheck_N.betweenCheckOnColumn(columnNode, type, numValue1, numValue2); } else { return RSValue.Some; } } @Override public BitMap exactCheckOnRow(Segment segment, int packId) throws IOException { Column column = segment.column(attr.columnId()); PackExtIndex extIndex = column.extIndex(packId); return extIndex.between(column, packId, numValue1, numValue2, strValue1, strValue2); } @Override public String toString() { if (strValue1 == null && strValue2 == null) { return String.format("%s($%s: %s, %s)", this.getClass().getSimpleName(), attr, numValue1, numValue2); } else { return String.format("%s($%s: %s, %s)", this.getClass().getSimpleName(), attr, strValue1, strValue2); } } }