001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.client; 019 020import static org.junit.jupiter.api.Assertions.assertEquals; 021import static org.junit.jupiter.api.Assertions.assertFalse; 022import static org.junit.jupiter.api.Assertions.assertNull; 023import static org.junit.jupiter.api.Assertions.assertTrue; 024 025import java.io.IOException; 026import org.apache.hadoop.hbase.HBaseTestingUtil; 027import org.apache.hadoop.hbase.TableName; 028import org.apache.hadoop.hbase.testclassification.ClientTests; 029import org.apache.hadoop.hbase.testclassification.MediumTests; 030import org.apache.hadoop.hbase.util.Bytes; 031import org.junit.jupiter.api.AfterAll; 032import org.junit.jupiter.api.BeforeAll; 033import org.junit.jupiter.api.Tag; 034import org.junit.jupiter.api.Test; 035 036/** 037 * With filter we may stop at a middle of row and think that we still have more cells for the 038 * current row but actually all the remaining cells will be filtered out by the filter. So it will 039 * lead to a Result that mayHaveMoreCellsInRow is true but actually there are no cells for the same 040 * row. Here we want to test if our limited scan still works. 041 */ 042@Tag(MediumTests.TAG) 043@Tag(ClientTests.TAG) 044public class TestLimitedScanWithFilter { 045 046 private static final HBaseTestingUtil UTIL = new HBaseTestingUtil(); 047 048 private static final TableName TABLE_NAME = TableName.valueOf("TestRegionScanner"); 049 050 private static final byte[] FAMILY = Bytes.toBytes("cf"); 051 052 private static final byte[][] CQS = 053 { Bytes.toBytes("cq1"), Bytes.toBytes("cq2"), Bytes.toBytes("cq3"), Bytes.toBytes("cq4") }; 054 055 private static int ROW_COUNT = 10; 056 057 @BeforeAll 058 public static void setUp() throws Exception { 059 UTIL.startMiniCluster(1); 060 try (Table table = UTIL.createTable(TABLE_NAME, FAMILY)) { 061 for (int i = 0; i < ROW_COUNT; i++) { 062 Put put = new Put(Bytes.toBytes(i)); 063 for (int j = 0; j < CQS.length; j++) { 064 put.addColumn(FAMILY, CQS[j], Bytes.toBytes((j + 1) * i)); 065 } 066 table.put(put); 067 } 068 } 069 } 070 071 @AfterAll 072 public static void tearDown() throws Exception { 073 UTIL.shutdownMiniCluster(); 074 } 075 076 @Test 077 public void testCompleteResult() throws IOException { 078 int limit = 5; 079 Scan scan = 080 new Scan().setFilter(new ColumnCountOnRowFilter(2)).setMaxResultSize(1).setLimit(limit); 081 try (Table table = UTIL.getConnection().getTable(TABLE_NAME); 082 ResultScanner scanner = table.getScanner(scan)) { 083 for (int i = 0; i < limit; i++) { 084 Result result = scanner.next(); 085 assertEquals(i, Bytes.toInt(result.getRow())); 086 assertEquals(2, result.size()); 087 assertFalse(result.mayHaveMoreCellsInRow()); 088 assertEquals(i, Bytes.toInt(result.getValue(FAMILY, CQS[0]))); 089 assertEquals(2 * i, Bytes.toInt(result.getValue(FAMILY, CQS[1]))); 090 } 091 assertNull(scanner.next()); 092 } 093 } 094 095 @Test 096 public void testAllowPartial() throws IOException { 097 int limit = 5; 098 Scan scan = new Scan().setFilter(new ColumnCountOnRowFilter(2)).setMaxResultSize(1) 099 .setAllowPartialResults(true).setLimit(limit); 100 try (Table table = UTIL.getConnection().getTable(TABLE_NAME); 101 ResultScanner scanner = table.getScanner(scan)) { 102 for (int i = 0; i < 2 * limit; i++) { 103 int key = i / 2; 104 Result result = scanner.next(); 105 assertEquals(key, Bytes.toInt(result.getRow())); 106 assertEquals(1, result.size()); 107 assertTrue(result.mayHaveMoreCellsInRow()); 108 int cqIndex = i % 2; 109 assertEquals(key * (cqIndex + 1), Bytes.toInt(result.getValue(FAMILY, CQS[cqIndex]))); 110 } 111 assertNull(scanner.next()); 112 } 113 } 114 115 @Test 116 public void testBatchAllowPartial() throws IOException { 117 int limit = 5; 118 Scan scan = new Scan().setFilter(new ColumnCountOnRowFilter(3)).setBatch(2).setMaxResultSize(1) 119 .setAllowPartialResults(true).setLimit(limit); 120 try (Table table = UTIL.getConnection().getTable(TABLE_NAME); 121 ResultScanner scanner = table.getScanner(scan)) { 122 for (int i = 0; i < 3 * limit; i++) { 123 int key = i / 3; 124 Result result = scanner.next(); 125 assertEquals(key, Bytes.toInt(result.getRow())); 126 assertEquals(1, result.size()); 127 assertTrue(result.mayHaveMoreCellsInRow()); 128 int cqIndex = i % 3; 129 assertEquals(key * (cqIndex + 1), Bytes.toInt(result.getValue(FAMILY, CQS[cqIndex]))); 130 } 131 assertNull(scanner.next()); 132 } 133 } 134 135 @Test 136 public void testBatch() throws IOException { 137 int limit = 5; 138 Scan scan = new Scan().setFilter(new ColumnCountOnRowFilter(2)).setBatch(2).setMaxResultSize(1) 139 .setLimit(limit); 140 try (Table table = UTIL.getConnection().getTable(TABLE_NAME); 141 ResultScanner scanner = table.getScanner(scan)) { 142 for (int i = 0; i < limit; i++) { 143 Result result = scanner.next(); 144 assertEquals(i, Bytes.toInt(result.getRow())); 145 assertEquals(2, result.size()); 146 assertTrue(result.mayHaveMoreCellsInRow()); 147 assertEquals(i, Bytes.toInt(result.getValue(FAMILY, CQS[0]))); 148 assertEquals(2 * i, Bytes.toInt(result.getValue(FAMILY, CQS[1]))); 149 } 150 assertNull(scanner.next()); 151 } 152 } 153 154 @Test 155 public void testBatchAndFilterDiffer() throws IOException { 156 int limit = 5; 157 Scan scan = new Scan().setFilter(new ColumnCountOnRowFilter(3)).setBatch(2).setMaxResultSize(1) 158 .setLimit(limit); 159 try (Table table = UTIL.getConnection().getTable(TABLE_NAME); 160 ResultScanner scanner = table.getScanner(scan)) { 161 for (int i = 0; i < limit; i++) { 162 Result result = scanner.next(); 163 assertEquals(i, Bytes.toInt(result.getRow())); 164 assertEquals(2, result.size()); 165 assertTrue(result.mayHaveMoreCellsInRow()); 166 assertEquals(i, Bytes.toInt(result.getValue(FAMILY, CQS[0]))); 167 assertEquals(2 * i, Bytes.toInt(result.getValue(FAMILY, CQS[1]))); 168 result = scanner.next(); 169 assertEquals(i, Bytes.toInt(result.getRow())); 170 assertEquals(1, result.size()); 171 assertFalse(result.mayHaveMoreCellsInRow()); 172 assertEquals(3 * i, Bytes.toInt(result.getValue(FAMILY, CQS[2]))); 173 } 174 assertNull(scanner.next()); 175 } 176 } 177}