use of org.apache.phoenix.query.KeyRange in project phoenix by apache.
the class SkipScanFilter method readFields.
@Override
public void readFields(DataInput in) throws IOException {
RowKeySchema schema = new RowKeySchema();
schema.readFields(in);
int andLen = in.readInt();
boolean includeMultipleVersions = false;
if (andLen < 0) {
andLen = -andLen;
includeMultipleVersions = true;
}
int[] slotSpan = new int[andLen];
List<List<KeyRange>> slots = Lists.newArrayListWithExpectedSize(andLen);
for (int i = 0; i < andLen; i++) {
int orLenWithSlotSpan = in.readInt();
int orLen = orLenWithSlotSpan;
/*
* For 4.2+ clients, we serialize the slotSpan array. To maintain backward
* compatibility, we encode the slotSpan values with the size of the list
* of key ranges. We reserve 21 bits for the key range list and 10 bits
* for the slotSpan value (up to 1024 which should be plenty).
*/
if (orLenWithSlotSpan < 0) {
orLenWithSlotSpan = -orLenWithSlotSpan - 1;
slotSpan[i] = orLenWithSlotSpan >>> KEY_RANGE_LENGTH_BITS;
orLen = (orLenWithSlotSpan << SLOT_SPAN_BITS) >>> SLOT_SPAN_BITS;
}
List<KeyRange> orClause = Lists.newArrayListWithExpectedSize(orLen);
slots.add(orClause);
for (int j = 0; j < orLen; j++) {
KeyRange range = KeyRange.read(in);
orClause.add(range);
}
}
this.init(slots, slotSpan, schema, includeMultipleVersions);
}
use of org.apache.phoenix.query.KeyRange in project phoenix by apache.
the class MultiCfQueryExecIT method testGuidePostsForMultiCFsOverUnevenDistrib.
@Test
public void testGuidePostsForMultiCFsOverUnevenDistrib() throws Exception {
Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
Connection conn = DriverManager.getConnection(getUrl(), props);
conn.createStatement().execute("CREATE TABLE " + fullTableName + " (K1 CHAR(1) NOT NULL, " + "K2 VARCHAR NOT NULL, " + "CF1.A INTEGER, " + "CF2.B INTEGER, " + "CF3.C INTEGER, " + "CF4.D INTEGER, " + "CF5.E INTEGER, " + "CF6.F INTEGER " + "CONSTRAINT PK PRIMARY KEY (K1,K2)) SPLIT ON ('B','C','D')");
for (int i = 0; i < 100; i++) {
String upsert = "UPSERT INTO " + fullTableName + "(K1,K2,A) VALUES('" + Character.toString((char) ('A' + i % 10)) + "','" + (i * 10) + "'," + i + ")";
conn.createStatement().execute(upsert);
if (i % 10 == 0) {
conn.createStatement().execute("UPSERT INTO " + fullTableName + "(K1,K2,F) VALUES('" + Character.toString((char) ('A' + i % 10)) + "','" + (i * 10) + "'," + (i * 10) + ")");
}
}
conn.commit();
try {
analyzeTable(conn, fullTableName);
PreparedStatement statement = conn.prepareStatement("select count(*) from " + fullTableName + " where f < 400");
ResultSet rs = statement.executeQuery();
assertTrue(rs.next());
assertEquals(4, rs.getLong(1));
assertFalse(rs.next());
List<KeyRange> splits = getAllSplits(conn, fullTableName, "f < 400", "COUNT(*)");
// Uses less populated column f
assertEquals(14, splits.size());
// Uses more populated column a
splits = getAllSplits(conn, fullTableName, "a < 80", "COUNT(*)");
assertEquals(104, splits.size());
} finally {
conn.close();
}
}
use of org.apache.phoenix.query.KeyRange in project phoenix by apache.
the class MultiCfQueryExecIT method testGuidePostsRetrievedForMultiCF.
@Test
public void testGuidePostsRetrievedForMultiCF() throws Exception {
Connection conn;
PreparedStatement stmt;
ResultSet rs;
Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
conn = DriverManager.getConnection(getUrl(), props);
conn.createStatement().execute("CREATE TABLE " + fullTableName + " ( k INTEGER PRIMARY KEY, A.V1 VARCHAR, B.V2 VARCHAR, C.V3 VARCHAR)");
stmt = conn.prepareStatement("UPSERT INTO " + fullTableName + " VALUES(?,?,?,?)");
stmt.setInt(1, 1);
stmt.setString(2, "A");
stmt.setString(3, "B");
stmt.setString(4, "C");
stmt.execute();
conn.commit();
stmt = conn.prepareStatement("UPSERT INTO " + fullTableName + " VALUES(?,?,?,?)");
stmt.setInt(1, 2);
stmt.setString(2, "D");
stmt.setString(3, "E");
stmt.setString(4, "F");
stmt.execute();
conn.commit();
stmt = conn.prepareStatement("UPSERT INTO " + fullTableName + "(k, A.V1, C.V3) VALUES(?,?,?)");
stmt.setInt(1, 3);
stmt.setString(2, "E");
stmt.setString(3, "X");
stmt.execute();
conn.commit();
stmt = conn.prepareStatement("UPSERT INTO " + fullTableName + "(k, A.V1, C.V3) VALUES(?,?,?)");
stmt.setInt(1, 4);
stmt.setString(2, "F");
stmt.setString(3, "F");
stmt.execute();
conn.commit();
analyzeTable(conn, fullTableName);
rs = conn.createStatement().executeQuery("SELECT B.V2 FROM " + fullTableName + " WHERE B.V2 = 'B'");
assertTrue(rs.next());
assertEquals("B", rs.getString(1));
List<KeyRange> splits = getAllSplits(conn, fullTableName, "C.V3 = 'X'", "A.V1");
assertEquals(5, splits.size());
splits = getAllSplits(conn, fullTableName, "B.V2 = 'B'", "B.V2");
assertEquals(3, splits.size());
conn.close();
}
use of org.apache.phoenix.query.KeyRange in project phoenix by apache.
the class AggregateIT method testAvgGroupByOrderPreserving.
private void testAvgGroupByOrderPreserving(Connection conn, String tableName, int nGuidePosts) throws SQLException, IOException {
String query = "SELECT k1,avg(k2) FROM " + tableName + " GROUP BY k1";
ResultSet rs = conn.createStatement().executeQuery(query);
assertTrue(rs.next());
assertEquals("a", rs.getString(1));
assertEquals(3, rs.getInt(2));
assertTrue(rs.next());
assertEquals("b", rs.getString(1));
assertEquals(5, rs.getInt(2));
assertTrue(rs.next());
assertEquals("j", rs.getString(1));
assertEquals(4, rs.getInt(2));
assertTrue(rs.next());
assertEquals("n", rs.getString(1));
assertEquals(2, rs.getInt(2));
assertFalse(rs.next());
rs = conn.createStatement().executeQuery("EXPLAIN " + query);
assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER " + tableName + "\n" + " SERVER FILTER BY FIRST KEY ONLY\n" + " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY [K1]", QueryUtil.getExplainPlan(rs));
TestUtil.analyzeTable(conn, tableName);
List<KeyRange> splits = TestUtil.getAllSplits(conn, tableName);
assertEquals(nGuidePosts, splits.size());
}
use of org.apache.phoenix.query.KeyRange in project phoenix by apache.
the class RoundDecimalExpression method newKeyPart.
@Override
public KeyPart newKeyPart(final KeyPart childPart) {
return new KeyPart() {
private final List<Expression> extractNodes = Collections.<Expression>singletonList(RoundDecimalExpression.this);
@Override
public PColumn getColumn() {
return childPart.getColumn();
}
@Override
public List<Expression> getExtractNodes() {
return extractNodes;
}
@Override
public KeyRange getKeyRange(CompareFilter.CompareOp op, Expression rhs) {
final BigDecimal rhsDecimal = (BigDecimal) PDecimal.INSTANCE.toObject(evaluateExpression(rhs));
// than needed for a match, it's impossible for there to be any matches
if (op == CompareFilter.CompareOp.EQUAL && !hasEnoughPrecisionToProduce(rhsDecimal)) {
return KeyRange.EMPTY_RANGE;
}
// if the decimal needs to be rounded, round it such that the given
// operator will still be valid
BigDecimal roundedDecimal = roundAndPreserveOperator(rhsDecimal, op);
// the range of big decimals that could be rounded to produce the rounded result
// alternatively, the "rounding bucket" that this decimal falls into
final KeyRange equalityRange = getInputRangeProducing(roundedDecimal);
boolean lowerInclusive = equalityRange.isLowerInclusive();
boolean upperInclusive = equalityRange.isUpperInclusive();
byte[] lowerRange = KeyRange.UNBOUND;
byte[] upperRange = KeyRange.UNBOUND;
switch(op) {
case EQUAL:
return equalityRange;
case GREATER:
// from the equality range and up, NOT including the equality range
lowerRange = equalityRange.getUpperRange();
lowerInclusive = !equalityRange.isUpperInclusive();
break;
case GREATER_OR_EQUAL:
// from the equality range and up, including the equality range
lowerRange = equalityRange.getLowerRange();
break;
case LESS:
// from the equality range and down, NOT including the equality range
upperRange = equalityRange.getLowerRange();
upperInclusive = !equalityRange.isLowerInclusive();
break;
case LESS_OR_EQUAL:
// from the equality range and down, including the equality range
upperRange = equalityRange.getUpperRange();
break;
default:
throw new AssertionError("Invalid CompareOp: " + op);
}
return KeyRange.getKeyRange(lowerRange, lowerInclusive, upperRange, upperInclusive);
}
/**
* Produces a the given decimal rounded to this rounding expression's scale. If the
* decimal requires more scale precision to produce than this expression has, as in
* ROUND(?, 2) > 2.0098974, it ensures that the decimal is rounded such that the
* given operator will still produce correct results.
* @param decimal the decimal to round with this expression's scale
* @param op the operator to preserve comparison with in the event of lost precision
* @return the rounded decimal
*/
private BigDecimal roundAndPreserveOperator(BigDecimal decimal, CompareFilter.CompareOp op) {
final BigDecimal rounded = roundToScale(decimal);
// if we lost information, make sure that the rounding didn't break the operator
if (!hasEnoughPrecisionToProduce(decimal)) {
switch(op) {
case GREATER_OR_EQUAL:
// 'ROUND(dec, 2) >= 2.01' but should be 'ROUND(dec, 2) >= 2.02'
if (decimal.compareTo(rounded) > 0) {
return stepNextInScale(rounded);
}
break;
case GREATER:
// 'ROUND(dec, 2) > 2.02' but should be 'ROUND(dec, 2) > 2.01'
if (decimal.compareTo(rounded) < 0) {
return stepPrevInScale(rounded);
}
break;
case LESS_OR_EQUAL:
// 'ROUND(dec, 2) < 2.02' but should be 'ROUND(dec, 2) < 2.01'
if (decimal.compareTo(rounded) < 0) {
return stepPrevInScale(rounded);
}
break;
case LESS:
// 'ROUND(dec, 2) <= 2.01' but should be 'ROUND(dec, 2) <= 2.02'
if (decimal.compareTo(rounded) > 0) {
return stepNextInScale(rounded);
}
break;
}
}
// otherwise, rounding has not affected the operator, so return normally
return rounded;
}
@Override
public PTable getTable() {
return childPart.getTable();
}
};
}
Aggregations