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