Skip to content

Commit a3bd1b5

Browse files
author
Kadir Ozdemir
committed
Support for raw_row_size()
1 parent 72cfa09 commit a3bd1b5

File tree

9 files changed

+177
-11
lines changed

9 files changed

+177
-11
lines changed

phoenix-core-client/src/main/java/org/apache/phoenix/compile/StatementContext.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ public class StatementContext {
9090
private boolean totalSegmentsFunction = false;
9191
private Integer totalSegmentsValue;
9292
private boolean hasRowSizeFunction = false;
93+
private boolean hasRawRowSizeFunction = false;
9394

9495
public StatementContext(PhoenixStatement statement) {
9596
this(statement, new Scan());
@@ -123,6 +124,7 @@ public StatementContext(StatementContext context) {
123124
this.totalSegmentsFunction = context.totalSegmentsFunction;
124125
this.totalSegmentsValue = context.totalSegmentsValue;
125126
this.hasRowSizeFunction = context.hasRowSizeFunction;
127+
this.hasRawRowSizeFunction = context.hasRawRowSizeFunction;
126128
}
127129

128130
/**
@@ -454,10 +456,18 @@ public boolean hasRowSizeFunction() {
454456
return hasRowSizeFunction;
455457
}
456458

459+
public boolean hasRawRowSizeFunction() {
460+
return hasRawRowSizeFunction;
461+
}
462+
457463
public void setHasRowSizeFunctionFunction(boolean hasRowSizeFunction) {
458464
this.hasRowSizeFunction = hasRowSizeFunction;
459465
}
460466

467+
public void setHasRawRowSizeFunctionFunction(boolean hasRawRowSizeFunction) {
468+
this.hasRawRowSizeFunction = hasRawRowSizeFunction;
469+
}
470+
461471
public Integer getTotalSegmentsValue() {
462472
return totalSegmentsValue;
463473
}

phoenix-core-client/src/main/java/org/apache/phoenix/compile/WhereCompiler.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ private static void setScanFilter(StatementContext context, FilterableStatement
543543
}
544544
} else if (
545545
whereClause != null && !ExpressionUtil.evaluatesToTrue(whereClause)
546-
&& !context.hasRowSizeFunction()
546+
&& !context.hasRowSizeFunction() && !context.hasRawRowSizeFunction()
547547
) {
548548
Filter filter = null;
549549
final Counter counter = new Counter();
@@ -604,7 +604,13 @@ public Void visit(KeyValueColumnExpression expression) {
604604
}
605605
scan.setFilter(filter);
606606
} else if (whereClause != null && !ExpressionUtil.evaluatesToTrue(whereClause)) {
607-
scan.setFilter(new RowLevelFilter(whereClause));
607+
if (context.hasRawRowSizeFunction()) {
608+
scan.setFilter(new RowLevelFilter(whereClause, true));
609+
scan.setRaw(true);
610+
scan.readAllVersions();
611+
} else {
612+
scan.setFilter(new RowLevelFilter(whereClause, false));
613+
}
608614
}
609615

610616
ScanRanges scanRanges = context.getScanRanges();

phoenix-core-client/src/main/java/org/apache/phoenix/expression/ExpressionType.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public enum ExpressionType {
3737
ReverseFunction(ReverseFunction.class),
3838
RowKey(RowKeyColumnExpression.class),
3939
RowSizeFunction(RowSizeFunction.class),
40+
RawRowSizeFunction(RawRowSizeFunction.class),
4041
KeyValue(KeyValueColumnExpression.class),
4142
LiteralValue(LiteralExpression.class),
4243
RoundFunction(RoundFunction.class),
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
package org.apache.phoenix.expression.function;
19+
20+
import java.sql.SQLException;
21+
import java.util.List;
22+
import org.apache.phoenix.expression.Expression;
23+
import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
24+
import org.apache.phoenix.parse.RawRowSizeParseNode;
25+
26+
/**
27+
* Function to return the total size of the all HBase cells versions and delete markers for a given
28+
* row
29+
*/
30+
@BuiltInFunction(name = RawRowSizeFunction.NAME, nodeClass = RawRowSizeParseNode.class, args = {})
31+
public class RawRowSizeFunction extends RowSizeFunction {
32+
33+
public static final String NAME = "RAW_ROW_SIZE";
34+
35+
public RawRowSizeFunction() {
36+
}
37+
38+
public RawRowSizeFunction(List<Expression> children) throws SQLException {
39+
super(children);
40+
}
41+
}

phoenix-core-client/src/main/java/org/apache/phoenix/filter/RowLevelFilter.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,15 @@
3232
* Filter used when expressions reference to the entire row
3333
*/
3434
public class RowLevelFilter extends BooleanExpressionFilter {
35+
private boolean allVersions = false;
3536
private boolean keepRow = false;
3637

3738
public RowLevelFilter() {
3839
}
3940

40-
public RowLevelFilter(Expression expression) {
41+
public RowLevelFilter(Expression expression, boolean allVersions) {
4142
super(expression);
43+
this.allVersions = allVersions;
4244
}
4345

4446
@Override
@@ -54,7 +56,7 @@ public ReturnCode filterKeyValue(Cell v) {
5456

5557
@Override
5658
public ReturnCode filterCell(Cell v) {
57-
return ReturnCode.INCLUDE_AND_NEXT_COL;
59+
return allVersions ? ReturnCode.INCLUDE : ReturnCode.INCLUDE_AND_NEXT_COL;
5860
}
5961

6062
@Override
@@ -72,11 +74,13 @@ public boolean filterRow() {
7274
@Override
7375
public void readFields(DataInput input) throws IOException {
7476
super.readFields(input);
77+
allVersions = input.readBoolean();
7578
}
7679

7780
@Override
7881
public void write(DataOutput output) throws IOException {
7982
super.write(output);
83+
output.writeBoolean(allVersions);
8084
}
8185

8286
public static RowLevelFilter parseFrom(final byte[] pbBytes) throws DeserializationException {

phoenix-core-client/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ private static void initializeScan(QueryPlan plan, Integer perScanLimit, Integer
285285
}
286286
// Add FirstKeyOnlyFilter or EmptyColumnOnlyFilter if there are no references
287287
// to key value columns. We use FirstKeyOnlyFilter when possible
288-
if (keyOnlyFilter && !context.hasRowSizeFunction()) {
288+
if (keyOnlyFilter && !context.hasRowSizeFunction() && !context.hasRawRowSizeFunction()) {
289289
byte[] ecf = SchemaUtil.getEmptyColumnFamily(table);
290290
byte[] ecq = table.getEncodingScheme() == NON_ENCODED_QUALIFIERS
291291
? QueryConstants.EMPTY_COLUMN_BYTES
@@ -361,17 +361,20 @@ private static void initializeScan(QueryPlan plan, Integer perScanLimit, Integer
361361
if (optimizeProjection) {
362362
optimizeProjection(context, scan, table, statement);
363363
}
364-
if (context.hasRowSizeFunction()) {
364+
if (context.hasRowSizeFunction() || context.hasRawRowSizeFunction()) {
365365
scan.getFamilyMap().clear();
366-
ScanUtil.removePageFilter(scan);
366+
if (context.hasRawRowSizeFunction()) {
367+
scan.setRaw(true);
368+
scan.readAllVersions();
369+
}
367370
}
368371
}
369372
}
370373

371374
private static void setQualifierRanges(boolean keyOnlyFilter, PTable table, Scan scan,
372375
StatementContext context) throws SQLException {
373376
if (
374-
!context.hasRowSizeFunction()
377+
!context.hasRowSizeFunction() && !context.hasRawRowSizeFunction()
375378
&& EncodedColumnsUtil.useEncodedQualifierListOptimization(table, scan, context)
376379
) {
377380
Pair<Integer, Integer> minMaxQualifiers = new Pair<>();
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
package org.apache.phoenix.parse;
19+
20+
import java.sql.SQLException;
21+
import java.util.List;
22+
import org.apache.phoenix.compile.StatementContext;
23+
import org.apache.phoenix.expression.Expression;
24+
import org.apache.phoenix.expression.function.FunctionExpression;
25+
import org.apache.phoenix.expression.function.RawRowSizeFunction;
26+
27+
public class RawRowSizeParseNode extends RowSizeParseNode {
28+
29+
RawRowSizeParseNode(String name, List<ParseNode> children, BuiltInFunctionInfo info) {
30+
super(name, children, info);
31+
}
32+
33+
@Override
34+
public FunctionExpression create(List<Expression> children, StatementContext context)
35+
throws SQLException {
36+
// It does not take any parameters.
37+
if (children.size() != 0) {
38+
throw new IllegalArgumentException("RawRowSizeFunction does not take any parameters");
39+
}
40+
context.setHasRawRowSizeFunctionFunction(true);
41+
return new RawRowSizeFunction(children);
42+
}
43+
}

phoenix-core-client/src/main/java/org/apache/phoenix/util/EncodedColumnsUtil.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,8 @@ public static boolean useEncodedQualifierListOptimization(PTable table, Scan sca
141141
* on the scan to use this optimization. Disabling this optimization for tables with more than
142142
* one column family. See PHOENIX-3890.
143143
*/
144-
return !scan.isRaw() && !context.hasRowSizeFunction() && table.getColumnFamilies().size() == 1
145-
&& table.getImmutableStorageScheme() != null
144+
return !scan.isRaw() && !context.hasRowSizeFunction() && !context.hasRawRowSizeFunction()
145+
&& table.getColumnFamilies().size() == 1 && table.getImmutableStorageScheme() != null
146146
&& table.getImmutableStorageScheme() == ImmutableStorageScheme.ONE_CELL_PER_COLUMN
147147
&& usesEncodedColumnNames(table) && !table.isTransactional()
148148
&& !ScanUtil.hasDynamicColumns(table);

phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseAggregateIT.java

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ public void testCount() throws Exception {
267267
}
268268

269269
@Test
270-
public void testRowSizeFunction() throws Exception {
270+
public void testRowSizeFunctions() throws Exception {
271271
Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
272272
Connection conn = DriverManager.getConnection(getUrl(), props);
273273
String tableName = generateUniqueName();
@@ -352,6 +352,64 @@ public void testRowSizeFunction() throws Exception {
352352
} catch (SQLException e) {
353353
// expected
354354
}
355+
356+
// Make sure row size functions works with multi-tenant tables
357+
tableName = generateUniqueName();
358+
String sql = "CREATE TABLE " + tableName
359+
+ " (ORGANIZATION_ID VARCHAR NOT NULL, CONTAINER_ID VARCHAR, ENTITY_ID INTEGER,"
360+
+ " CONSTRAINT PK PRIMARY KEY (ORGANIZATION_ID, CONTAINER_ID)) MULTI_TENANT = TRUE";
361+
conn.createStatement().execute(sql);
362+
363+
conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES ('a','1', 11)");
364+
conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES ('b','2', 22)");
365+
conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES ('c','3', 33)");
366+
conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES ('d','1', 44)");
367+
conn.commit();
368+
conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES ('a','1', 12)");
369+
conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES ('a','2', 11)");
370+
conn.commit();
371+
conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES ('c','9', 11)");
372+
conn.commit();
373+
conn.createStatement().execute("DELETE FROM " + tableName + " WHERE organization_id='d'");
374+
conn.commit();
375+
376+
queryBuilder = new QueryBuilder().setSelectExpression("ORGANIZATION_ID, sum(row_size())")
377+
.setFullTableName(tableName).setGroupByClause("ORGANIZATION_ID");
378+
rs = executeQuery(conn, queryBuilder);
379+
assertTrue(rs.next());
380+
assertEquals("a", rs.getString(1));
381+
assertEquals(118, rs.getLong(2));
382+
assertTrue(rs.next());
383+
assertEquals("b", rs.getString(1));
384+
assertEquals(59, rs.getLong(2));
385+
assertTrue(rs.next());
386+
assertEquals("c", rs.getString(1));
387+
assertEquals(118, rs.getLong(2));
388+
assertFalse(rs.next());
389+
390+
// Make sure raw_row_size() computation includes all cell versions and delete markers
391+
queryBuilder = new QueryBuilder().setSelectExpression("ORGANIZATION_ID, sum(raw_row_size())")
392+
.setFullTableName(tableName).setGroupByClause("ORGANIZATION_ID");
393+
rs = executeQuery(conn, queryBuilder);
394+
395+
assertTrue(rs.next());
396+
assertEquals("a", rs.getString(1));
397+
// There are 3 row versions, each version is 59 bytes and so 3 * 59 = 177
398+
assertEquals(177, rs.getLong(2));
399+
assertTrue(rs.next());
400+
assertEquals("b", rs.getString(1));
401+
// There is one row version and one version is 59 bytes
402+
assertEquals(59, rs.getLong(2));
403+
assertTrue(rs.next());
404+
assertEquals("c", rs.getString(1));
405+
// There are two versions, 2 * 59 = 118
406+
assertEquals(118, rs.getLong(2));
407+
assertTrue(rs.next());
408+
assertEquals("d", rs.getString(1));
409+
// One row version (59 bytes) and plus delete family marker
410+
assertEquals(83, rs.getLong(2));
411+
assertFalse(rs.next());
412+
355413
conn.close();
356414
}
357415

0 commit comments

Comments
 (0)