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.filter; 019 020import static org.junit.Assert.assertEquals; 021import static org.junit.Assert.assertTrue; 022import java.io.IOException; 023import java.util.ArrayList; 024import java.util.Arrays; 025import java.util.List; 026import org.apache.hadoop.hbase.Cell; 027import org.apache.hadoop.hbase.CellComparator; 028import org.apache.hadoop.hbase.CompareOperator; 029import org.apache.hadoop.hbase.HBaseClassTestRule; 030import org.apache.hadoop.hbase.HBaseTestingUtility; 031import org.apache.hadoop.hbase.HConstants; 032import org.apache.hadoop.hbase.TableName; 033import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 034import org.apache.hadoop.hbase.client.Durability; 035import org.apache.hadoop.hbase.client.Put; 036import org.apache.hadoop.hbase.client.RegionInfo; 037import org.apache.hadoop.hbase.client.RegionInfoBuilder; 038import org.apache.hadoop.hbase.client.Scan; 039import org.apache.hadoop.hbase.client.TableDescriptor; 040import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 041import org.apache.hadoop.hbase.regionserver.HRegion; 042import org.apache.hadoop.hbase.regionserver.InternalScanner; 043import org.apache.hadoop.hbase.testclassification.FilterTests; 044import org.apache.hadoop.hbase.testclassification.SmallTests; 045import org.apache.hadoop.hbase.util.Bytes; 046import org.junit.After; 047import org.junit.Before; 048import org.junit.ClassRule; 049import org.junit.Rule; 050import org.junit.Test; 051import org.junit.experimental.categories.Category; 052import org.junit.rules.TestName; 053import org.slf4j.Logger; 054import org.slf4j.LoggerFactory; 055 056/** 057 * Test qualifierFilter with empty qualifier column 058 */ 059@Category({FilterTests.class, SmallTests.class}) 060public class TestQualifierFilterWithEmptyQualifier { 061 062 private final static Logger LOG 063 = LoggerFactory.getLogger(TestQualifierFilterWithEmptyQualifier.class); 064 @ClassRule 065 public static final HBaseClassTestRule CLASS_RULE = 066 HBaseClassTestRule.forClass(TestQualifierFilterWithEmptyQualifier.class); 067 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 068 private HRegion region; 069 070 @Rule 071 public TestName name = new TestName(); 072 073 private static final byte[][] ROWS = 074 { Bytes.toBytes("testRowOne-0"), Bytes.toBytes("testRowOne-1"), 075 Bytes.toBytes("testRowOne-2"), Bytes.toBytes("testRowOne-3") }; 076 private static final byte[] FAMILY = Bytes.toBytes("testFamily"); 077 private static final byte[][] QUALIFIERS = {HConstants.EMPTY_BYTE_ARRAY, 078 Bytes.toBytes("testQualifier")}; 079 private static final byte[] VALUE = Bytes.toBytes("testValueOne"); 080 private long numRows = (long) ROWS.length; 081 082 @Before 083 public void setUp() throws Exception { 084 TableDescriptor htd = TableDescriptorBuilder 085 .newBuilder(TableName.valueOf("TestQualifierFilter")) 086 .setColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder(FAMILY).build()).build(); 087 RegionInfo info = RegionInfoBuilder.newBuilder(htd.getTableName()).build(); 088 this.region = HBaseTestingUtility 089 .createRegionAndWAL(info, TEST_UTIL.getDataTestDir(), TEST_UTIL.getConfiguration(), htd); 090 091 // Insert data 092 for (byte[] ROW : ROWS) { 093 Put p = new Put(ROW); 094 p.setDurability(Durability.SKIP_WAL); 095 for (byte[] QUALIFIER : QUALIFIERS) { 096 p.addColumn(FAMILY, QUALIFIER, VALUE); 097 } 098 this.region.put(p); 099 } 100 101 // Flush 102 this.region.flush(true); 103 } 104 105 @After 106 public void tearDown() throws Exception { 107 HBaseTestingUtility.closeRegionAndWAL(region); 108 } 109 110 @Test 111 public void testQualifierFilterWithEmptyColumn() throws IOException { 112 long colsPerRow = 2; 113 long expectedKeys = colsPerRow / 2; 114 Filter f = new QualifierFilter(CompareOperator.EQUAL, 115 new BinaryComparator(QUALIFIERS[0])); 116 Scan s = new Scan(); 117 s.setFilter(f); 118 verifyScanNoEarlyOut(s, this.numRows, expectedKeys); 119 120 expectedKeys = colsPerRow / 2; 121 f = new QualifierFilter(CompareOperator.EQUAL, 122 new BinaryComparator(QUALIFIERS[1])); 123 s = new Scan(); 124 s.setFilter(f); 125 verifyScanNoEarlyOut(s, this.numRows, expectedKeys); 126 127 expectedKeys = colsPerRow / 2; 128 f = new QualifierFilter(CompareOperator.GREATER, 129 new BinaryComparator(QUALIFIERS[0])); 130 s = new Scan(); 131 s.setFilter(f); 132 verifyScanNoEarlyOut(s, this.numRows, expectedKeys); 133 134 expectedKeys = colsPerRow; 135 f = new QualifierFilter(CompareOperator.GREATER_OR_EQUAL, 136 new BinaryComparator(QUALIFIERS[0])); 137 s = new Scan(); 138 s.setFilter(f); 139 verifyScanNoEarlyOut(s, this.numRows, expectedKeys); 140 } 141 142 private void verifyScanNoEarlyOut(Scan s, long expectedRows, 143 long expectedKeys) 144 throws IOException { 145 InternalScanner scanner = this.region.getScanner(s); 146 List<Cell> results = new ArrayList<>(); 147 int i = 0; 148 for (boolean done = true; done; i++) { 149 done = scanner.next(results); 150 Arrays.sort(results.toArray(new Cell[results.size()]), 151 CellComparator.getInstance()); 152 LOG.info("counter=" + i + ", " + results); 153 if(results.isEmpty()) { 154 break; 155 } 156 assertTrue("Scanned too many rows! Only expected " + expectedRows + 157 " total but already scanned " + (i+1), expectedRows > i); 158 assertEquals("Expected " + expectedKeys + " keys per row but " + 159 "returned " + results.size(), expectedKeys, results.size()); 160 results.clear(); 161 } 162 assertEquals("Expected " + expectedRows + " rows but scanned " + i + 163 " rows", expectedRows, i); 164 } 165}