Package org.lilyproject.hbaseindex

Source Code of org.lilyproject.hbaseindex.IndexTest

/*
* Copyright 2010 Outerthought bvba
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lilyproject.hbaseindex;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Arrays;

import com.gotometrics.orderly.Order;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.lilyproject.hadooptestfw.HBaseProxy;
import org.lilyproject.hadooptestfw.TestHelper;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;

// Important: while not done in these testcases, it is recommended to call QueryResult.close()
// when done using the QueryResult.

public class IndexTest {
    private static HBaseProxy HBASE_PROXY;

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        TestHelper.setupLogging();
        HBASE_PROXY = new HBaseProxy();
        HBASE_PROXY.start();
    }

    @AfterClass
    public static void tearDownAfterClass() throws Exception {
        HBASE_PROXY.stop();
    }

    @Test
    public void testSingleStringFieldIndex() throws Exception {
        final String INDEX_NAME = "singleStringField";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        indexDef.addStringField("field1");
        Index index = indexManager.getIndex(indexDef);

        // Create a few index entries, inserting them in non-sorted order
        String[] values = {"d", "a", "c", "e", "b"};

        for (int i = 0; i < values.length; i++) {
            IndexEntry entry = new IndexEntry(indexDef);
            entry.addField("field1", values[i]);
            entry.setIdentifier(Bytes.toBytes("key" + i));
            index.addEntry(entry);
        }

        Query query = new Query();
        query.setRangeCondition("field1", "b", "d");
        QueryResult result = index.performQuery(query);
        assertResultIds(result, "key4", "key2", "key0");
    }

    @Test
    public void testSingleByteFieldIndex() throws Exception {
        final String INDEX_NAME = "singleByteField";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        indexDef.addByteField("field1", 3);
        Index index = indexManager.getIndex(indexDef);

        // Create a few index entries, inserting them in non-sorted order
        byte[][] values = {Bytes.toBytes("aaa"), Bytes.toBytes("aab")};

        for (int i = 0; i < values.length; i++) {
            IndexEntry entry = new IndexEntry(indexDef);
            entry.addField("field1", values[i]);
            entry.setIdentifier(Bytes.toBytes("key" + i));
            index.addEntry(entry);
        }

        Query query = new Query();
        query.setRangeCondition("field1", Bytes.toBytes("aaa"), Bytes.toBytes("aab"));
        QueryResult result = index.performQuery(query);
        assertResultIds(result, "key0", "key1");
    }

    @Test
    public void testSingleIntFieldIndex() throws Exception {
        final String INDEX_NAME = "singleIntField";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        indexDef.addIntegerField("field1");
        Index index = indexManager.getIndex(indexDef);

        final int COUNT = 1000;
        final int MAXVALUE = Integer.MAX_VALUE;
        int[] values = new int[COUNT];

        for (int i = 0; i < COUNT; i++) {
            values[i] = (int) (Math.random() * MAXVALUE);
        }

        for (int value : values) {
            IndexEntry entry = new IndexEntry(indexDef);
            entry.addField("field1", value);
            entry.setIdentifier(Bytes.toBytes("key" + value));
            index.addEntry(entry);
        }

        Query query = new Query();
        query.setRangeCondition("field1", new Integer(0), new Integer(MAXVALUE));
        QueryResult result = index.performQuery(query);

        Arrays.sort(values);

        for (int value : values) {
            assertEquals("key" + value, Bytes.toString(result.next()));
        }

        assertNull(result.next());
    }

    @Test
    public void testSingleLongFieldIndex() throws Exception {
        final String INDEX_NAME = "singleLongField";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        indexDef.addLongField("field1");
        Index index = indexManager.getIndex(indexDef);

        long values[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE};
        for (long value : values) {
            IndexEntry entry = new IndexEntry(indexDef);
            entry.addField("field1", value);
            entry.setIdentifier(Bytes.toBytes("key" + value));
            index.addEntry(entry);
        }

        Query query = new Query();
        query.setRangeCondition("field1", Long.MIN_VALUE, Long.MAX_VALUE);
        QueryResult result = index.performQuery(query);

        for (long value : values) {
            assertEquals("key" + value, Bytes.toString(result.next()));
        }

        assertNull(result.next());
    }

    @Test
    public void testSingleFloatFieldIndex() throws Exception {
        final String INDEX_NAME = "singleFloatField";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        indexDef.addFloatField("field1");
        Index index = indexManager.getIndex(indexDef);

        float[] values = {55.45f, 63.88f, 55.46f, 55.47f, -0.3f};

        for (int i = 0; i < values.length; i++) {
            IndexEntry entry = new IndexEntry(indexDef);
            entry.addField("field1", values[i]);
            entry.setIdentifier(Bytes.toBytes("key" + i));
            index.addEntry(entry);
        }

        Query query = new Query();
        query.setRangeCondition("field1", new Float(55.44f), new Float(55.48f));
        QueryResult result = index.performQuery(query);
        assertResultIds(result, "key0", "key2", "key3");
    }

    @Test
    public void testSingleDecimalFieldIndex() throws Exception {
        final String INDEX_NAME = "singleDecimalField";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        indexDef.addDecimalField("field1");
        Index index = indexManager.getIndex(indexDef);

        String[] values = {"33.66", "-1", "-3.00007E77"};

        for (int i = 0; i < values.length; i++) {
            IndexEntry entry = new IndexEntry(indexDef);
            entry.addField("field1", new BigDecimal(values[i]));
            entry.setIdentifier(Bytes.toBytes("key" + i));
            index.addEntry(entry);
        }

        {
            Query query = new Query();
            query.setRangeCondition("field1", new BigDecimal(values[2]), new BigDecimal(values[0]));
            QueryResult result = index.performQuery(query);
            assertResultIds(result, "key2", "key1", "key0");
        }

        {
            Query query = new Query();
            query.addEqualsCondition("field1", new BigDecimal(values[2]));
            QueryResult result = index.performQuery(query);
            assertResultIds(result, "key2");
        }
    }

    @Test
    public void testDuplicateValuesIndex() throws Exception {
        final String INDEX_NAME = "duplicateValues";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        indexDef.addStringField("field1");

        Index index = indexManager.getIndex(indexDef);

        // Create a few index entries, inserting them in non-sorted order
        String[] values = {"a", "a", "a", "a", "b", "c", "d"};

        for (int i = 0; i < values.length; i++) {
            IndexEntry entry = new IndexEntry(indexDef);
            entry.addField("field1", values[i]);
            entry.setIdentifier(Bytes.toBytes("key" + i));
            index.addEntry(entry);
        }

        Query query = new Query();
        query.addEqualsCondition("field1", "a");
        QueryResult result = index.performQuery(query);

        assertResultSize(4, result);
    }

    @Test
    public void testMultiFieldIndex() throws Exception {
        final String INDEX_NAME = "multiField";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        indexDef.addIntegerField("field1");
        indexDef.addStringField("field2");

        Index index = indexManager.getIndex(indexDef);

        IndexEntry entry = new IndexEntry(indexDef);
        entry.addField("field1", 10);
        entry.addField("field2", "a");
        entry.setIdentifier(Bytes.toBytes("key1"));
        index.addEntry(entry);
        entry.setIdentifier(Bytes.toBytes("key2"));
        index.addEntry(entry);
        entry.setIdentifier(Bytes.toBytes("key3"));
        index.addEntry(entry);

        entry = new IndexEntry(indexDef);
        entry.addField("field1", 11);
        entry.addField("field2", "a");
        entry.setIdentifier(Bytes.toBytes("key4"));
        index.addEntry(entry);

        entry = new IndexEntry(indexDef);
        entry.addField("field1", 10);
        entry.addField("field2", "b");
        entry.setIdentifier(Bytes.toBytes("key5"));
        index.addEntry(entry);

        Query query = new Query();
        query.addEqualsCondition("field1", 10);
        query.addEqualsCondition("field2", "a");
        QueryResult result = index.performQuery(query);

        assertResultSize(3, result);
    }

    @Test
    public void testDeleteFromIndex() throws Exception {
        final String INDEX_NAME = "deleteFromIndex";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        indexDef.addStringField("field1");

        Index index = indexManager.getIndex(indexDef);

        // Add the entry
        IndexEntry entry = new IndexEntry(indexDef);
        entry.addField("field1", "foobar");
        entry.setIdentifier(Bytes.toBytes("key1"));
        index.addEntry(entry);

        // Test it is there
        Query query = new Query();
        query.addEqualsCondition("field1", "foobar");
        QueryResult result = index.performQuery(query);
        assertEquals("key1", Bytes.toString(result.next()));
        assertNull(result.next());

        // Delete the entry
        index.removeEntry(entry);

        // Test it is gone
        result = index.performQuery(query);
        assertNull(result.next());

        // Delete the entry again, this should not give an error
        index.removeEntry(entry);
    }

    @Test
    public void testNullIndex() throws Exception {
        final String INDEX_NAME = "nullIndex";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        indexDef.addStringField("field1");
        indexDef.addStringField("field2");

        Index index = indexManager.getIndex(indexDef);

        IndexEntry entry = new IndexEntry(indexDef);
        entry.addField("field1", "foobar");
        entry.setIdentifier(Bytes.toBytes("key1"));
        index.addEntry(entry);

        entry = new IndexEntry(indexDef);
        entry.setIdentifier(Bytes.toBytes("key2"));
        index.addEntry(entry);

        entry = new IndexEntry(indexDef);
        entry.addField("field2", "foobar");
        entry.setIdentifier(Bytes.toBytes("key3"));
        index.addEntry(entry);

        Query query = new Query();
        query.addEqualsCondition("field1", "foobar");
        query.addEqualsCondition("field2", null);
        QueryResult result = index.performQuery(query);
        assertResultIds(result, "key1");

        query = new Query();
        query.addEqualsCondition("field1", null);
        query.addEqualsCondition("field2", null);
        result = index.performQuery(query);
        assertResultIds(result, "key2");

        query = new Query();
        query.addEqualsCondition("field1", null);
        query.addEqualsCondition("field2", "foobar");
        result = index.performQuery(query);
        assertResultIds(result, "key3");
    }

    @Test
    public void testNotExistingIndex() throws Exception {
        final String INDEX_NAME = "notExisting";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        try {
            indexManager.getIndex(INDEX_NAME);
            fail("Expected an IndexNotFoundException.");
        } catch (IndexNotFoundException e) {
            // ok
        }
    }

    @Test
    public void testDeleteIndex() throws Exception {
        final String INDEX_NAME = "deleteIndex";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        indexDef.addStringField("foo");
        indexManager.getIndex(indexDef);

        indexManager.getIndex(INDEX_NAME);

        indexManager.deleteIndex(INDEX_NAME);

        try {
            indexManager.getIndex(INDEX_NAME);
            fail("Expected an IndexNotFoundException.");
        } catch (IndexNotFoundException e) {
            // ok
        }
    }

    @Test
    public void testIndexEntryVerificationIndex() throws Exception {
        final String INDEX_NAME = "indexEntryVerification";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        indexDef.addStringField("stringfield");
        indexDef.addFloatField("floatfield");

        indexManager.getIndex(indexDef);

        Index index = indexManager.getIndex(INDEX_NAME);

        IndexEntry entry = new IndexEntry(indexDef);
        try {
            entry.addField("nonexistingfield", "foobar");
            fail("Expected a MalformedIndexEntryException.");
        } catch (MalformedIndexEntryException e) {
            // ok
        }

        entry = new IndexEntry(indexDef);
        try {
            entry.addField("stringfield", new Integer(55));
            fail("Expected a MalformedIndexEntryException.");
        } catch (MalformedIndexEntryException e) {
            // ok
        }

        entry = new IndexEntry(indexDef);
        try {
            entry.addField("floatfield", "hello world");
            fail("Expected a MalformedIndexEntryException.");
        } catch (MalformedIndexEntryException e) {
            // ok
        }
    }

    @Test
    public void testStringPrefixQuery() throws Exception {
        final String INDEX_NAME = "stringPrefixQuery";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        indexDef.addStringField("field1");

        Index index = indexManager.getIndex(indexDef);

        String[] values = {"baard", "boer", "beek", "kanaal", "paard"};

        for (int i = 0; i < values.length; i++) {
            IndexEntry entry = new IndexEntry(indexDef);
            entry.addField("field1", values[i]);
            entry.setIdentifier(Bytes.toBytes("key" + i));
            index.addEntry(entry);
        }

        Query query = new Query();
        query.setRangeCondition("field1", "b", "b");
        QueryResult result = index.performQuery(query);
        assertResultIds(result, "key0", "key2", "key1");
    }

    /**
     * Test searching on a subset of the fields.
     */
    @Test
    public void testPartialQuery() throws Exception {
        final String INDEX_NAME = "partialQuery";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        indexDef.addStringField("field1");
        indexDef.addIntegerField("field2");
        indexDef.addStringField("field3");

        Index index = indexManager.getIndex(indexDef);

        for (int i = 0; i < 3; i++) {
            IndexEntry entry = new IndexEntry(indexDef);
            entry.addField("field1", "value A " + i);
            entry.addField("field2", 10 + i);
            entry.addField("field3", "value B " + i);
            entry.setIdentifier(Bytes.toBytes("key" + i));
            index.addEntry(entry);
        }

        // Search only on the leftmost field
        {
            Query query = new Query();
            query.addEqualsCondition("field1", "value A 0");
            QueryResult result = index.performQuery(query);
            assertResultIds(result, "key0");
        }

        // Search only on the two leftmost fields
        {
            Query query = new Query();
            query.addEqualsCondition("field1", "value A 0");
            query.addEqualsCondition("field2", 10);
            QueryResult result = index.performQuery(query);
            assertResultIds(result, "key0");
        }

        // Search only on the two leftmost fields, with range query on the second
        {
            Query query = new Query();
            query.addEqualsCondition("field1", "value A 0");
            query.setRangeCondition("field2", 9, 11);
            QueryResult result = index.performQuery(query);
            assertResultIds(result, "key0");
        }

        // Try searching on just the second field, should give error
        {
            Query query = new Query();
            query.addEqualsCondition("field2", 10);
            try {
                index.performQuery(query);
                fail("Exception expected");
            } catch (MalformedQueryException e) {
                //System.out.println(e.getMessage());
            }
        }

        // Try searching on just the second field, should give error
        {
            Query query = new Query();
            query.setRangeCondition("field2", 9, 11);
            try {
                index.performQuery(query);
                fail("Exception expected");
            } catch (MalformedQueryException e) {
                //System.out.println(e.getMessage());
            }
        }

        // Try not using all fields from left to right, should give error
        {
            Query query = new Query();
            query.addEqualsCondition("field1", "value A 0");
            // skip field 2
            query.addEqualsCondition("field3", "value B 0");
            try {
                index.performQuery(query);
                fail("Exception expected");
            } catch (MalformedQueryException e) {
                //System.out.println(e.getMessage());
            }
        }

        // Try not using all fields from left to right, should give error
        {
            Query query = new Query();
            query.addEqualsCondition("field1", "value A 0");
            // skip field 2
            query.setRangeCondition("field3", "a", "b");
            try {
                index.performQuery(query);
                fail("Exception expected");
            } catch (MalformedQueryException e) {
                //System.out.println(e.getMessage());
            }
        }
    }

    @Test
    public void testDataTypeChecks() throws Exception {
        final String INDEX_NAME = "dataTypeChecks";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        indexDef.addStringField("field1");
        indexDef.addIntegerField("field2");

        Index index = indexManager.getIndex(indexDef);

        //
        // Index entry checks
        //

        // First test correct situation
        IndexEntry entry = new IndexEntry(indexDef);
        entry.addField("field1", "a");
        entry.setIdentifier(Bytes.toBytes("1"));
        index.addEntry(entry);

        // Now test incorrect situation
        entry = new IndexEntry(indexDef);
        try {
            entry.addField("field1", 55);
            fail("Expected exception.");
        } catch (MalformedIndexEntryException e) {
            //System.out.println(e.getMessage());
        }

        //
        // Query checks
        //

        // First test correct situation
        Query query = new Query();
        query.addEqualsCondition("field1", "a");
        index.performQuery(query);

        // Now test incorrect situation
        query = new Query();
        query.addEqualsCondition("field1", 55);
        try {
            index.performQuery(query);
            fail("Expected exception.");
        } catch (MalformedQueryException e) {
            //System.out.println(e.getMessage());
        }
    }

    @Test
    public void testEmptyDefinition() throws Exception {
        final String INDEX_NAME = "emptyDef";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        try {
            indexManager.getIndex(indexDef);
            fail("Exception expected.");
        } catch (IllegalArgumentException e) {
        }
    }

    @Test
    public void testExclusiveRanges() throws Exception {
        final String INDEX_NAME = "exclusiveRanges";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        indexDef.addIntegerField("field1");
        Index index = indexManager.getIndex(indexDef);

        int[] values = {1, 2, 3, 4};
        for (int value : values) {
            IndexEntry entry = new IndexEntry(indexDef);
            entry.addField("field1", value);
            entry.setIdentifier(Bytes.toBytes("key" + value));
            index.addEntry(entry);
        }

        {
            Query query = new Query();
            query.setRangeCondition("field1", 1, 4);
            QueryResult result = index.performQuery(query);
            assertResultIds(result, "key1", "key2", "key3", "key4");
        }

        {
            Query query = new Query();
            query.setRangeCondition("field1", 1, 4, false, false);
            QueryResult result = index.performQuery(query);
            assertResultIds(result, "key2", "key3");
        }

        {
            Query query = new Query();
            query.setRangeCondition("field1", 1, 4, false, true);
            QueryResult result = index.performQuery(query);
            assertResultIds(result, "key2", "key3", "key4");
        }

        {
            Query query = new Query();
            query.setRangeCondition("field1", 1, 4, true, false);
            QueryResult result = index.performQuery(query);
            assertResultIds(result, "key1", "key2", "key3");
        }
    }

    @Test
    public void testMinMaxRanges() throws Exception {
        final String INDEX_NAME = "minmaxranges";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        indexDef.addIntegerField("field1");
        Index index = indexManager.getIndex(indexDef);

        Integer[] values = {null, Integer.MIN_VALUE, 1, 2, Integer.MAX_VALUE};
        for (int i = 0; i < values.length; i++) {
            IndexEntry entry = new IndexEntry(indexDef);
            entry.addField("field1", values[i]);
            entry.setIdentifier(Bytes.toBytes("key" + (i + 1)));
            index.addEntry(entry);
        }

        {
            Query query = new Query();
            query.setRangeCondition("field1", Query.MIN_VALUE, Query.MAX_VALUE);
            QueryResult result = index.performQuery(query);
            assertResultIds(result, "key1", "key2", "key3", "key4", "key5");
        }

        {
            Query query = new Query();
            query.setRangeCondition("field1", Query.MIN_VALUE, 0);
            QueryResult result = index.performQuery(query);
            assertResultIds(result, "key1", "key2");
        }

        {
            Query query = new Query();
            query.setRangeCondition("field1", 0, Query.MAX_VALUE);
            QueryResult result = index.performQuery(query);
            assertResultIds(result, "key3", "key4", "key5");
        }
    }

    @Test
    public void testDescendingIntIndex() throws Exception {
        final String INDEX_NAME = "descendingIntIndex";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        indexDef.setIdentifierOrder(Order.DESCENDING);
        IntegerIndexFieldDefinition fieldDef = indexDef.addIntegerField("field1");
        fieldDef.setOrder(Order.DESCENDING);
        Index index = indexManager.getIndex(indexDef);

        Integer[] values = {null, 1, 2, 2, 3};
        for (int i = 0; i < values.length; i++) {
            IndexEntry entry = new IndexEntry(indexDef);
            entry.addField("field1", values[i]);
            entry.setIdentifier(Bytes.toBytes("key" + (i + 1)));
            index.addEntry(entry);
        }

        {
            Query query = new Query();
            query.setRangeCondition("field1", Query.MIN_VALUE, Query.MAX_VALUE);
            QueryResult result = index.performQuery(query);
            assertResultIds(result, "key5", "key4", "key3", "key2", "key1");
        }

        {
            Query query = new Query();
            query.setRangeCondition("field1", 3, 1);
            QueryResult result = index.performQuery(query);
            assertResultIds(result, "key5", "key4", "key3", "key2");
        }
    }

    @Test
    public void testDescendingIntAscendingKeyIndex() throws Exception {
        final String INDEX_NAME = "descendingIntAscendingKey";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        IntegerIndexFieldDefinition fieldDef = indexDef.addIntegerField("field1");
        fieldDef.setOrder(Order.DESCENDING);
        Index index = indexManager.getIndex(indexDef);

        Integer[] values = {1, 1, 2, 2};
        for (int i = 0; i < values.length; i++) {
            IndexEntry entry = new IndexEntry(indexDef);
            entry.addField("field1", values[i]);
            entry.setIdentifier(Bytes.toBytes("key" + (i + 1)));
            index.addEntry(entry);
        }

        // The index on the value is descending, the identifiers themselves are ascending!

        Query query = new Query();
        query.setRangeCondition("field1", 2, 1);
        QueryResult result = index.performQuery(query);
        assertResultIds(result, "key3", "key4", "key1", "key2");
    }

    @Test
    public void testAscendingStringIndex() throws Exception {
        final String INDEX_NAME = "ascendingStringIndex";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        indexDef.setIdentifierOrder(Order.ASCENDING);
        StringIndexFieldDefinition fieldDef = indexDef.addStringField("field1");
        fieldDef.setOrder(Order.ASCENDING);
        Index index = indexManager.getIndex(indexDef);

        String[] values = {"a", "ab", "abc", "b"};
        for (int i = 0; i < values.length; i++) {
            IndexEntry entry = new IndexEntry(indexDef);
            entry.addField("field1", values[i]);
            entry.setIdentifier(Bytes.toBytes("key" + (i + 1)));
            index.addEntry(entry);
        }

        {
            Query query = new Query();
            query.setRangeCondition("field1", Query.MIN_VALUE, Query.MAX_VALUE);
            QueryResult result = index.performQuery(query);
            assertResultIds(result, "key1", "key2", "key3", "key4");
        }

        {
            Query query = new Query();
            query.setRangeCondition("field1", "a", "b");
            QueryResult result = index.performQuery(query);
            assertResultIds(result, "key1", "key2", "key3", "key4");
        }

        {
            Query query = new Query();
            query.setRangeCondition("field1", "a", "a");
            QueryResult result = index.performQuery(query);
            assertResultIds(result, "key1", "key2", "key3");
        }
    }

    @Test
    public void testDescendingStringIndex() throws Exception {
        final String INDEX_NAME = "descendingStringIndex";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        indexDef.setIdentifierOrder(Order.DESCENDING);
        StringIndexFieldDefinition fieldDef = indexDef.addStringField("field1");
        fieldDef.setOrder(Order.DESCENDING);
        Index index = indexManager.getIndex(indexDef);

        String[] values = {"a", "ab", "abc", "b"};
        for (int i = 0; i < values.length; i++) {
            IndexEntry entry = new IndexEntry(indexDef);
            entry.addField("field1", values[i]);
            entry.setIdentifier(Bytes.toBytes("key" + (i + 1)));
            index.addEntry(entry);
        }

//        {
//            Query query = new Query();
//            query.setRangeCondition("field1", Query.MIN_VALUE, Query.MAX_VALUE);
//            QueryResult result = index.performQuery(query);
//            assertResultIds(result, "key4", "key3", "key2", "key1");
//        }
//
//        {
//            Query query = new Query();
//            query.setRangeCondition("field1", "b", "a");
//            QueryResult result = index.performQuery(query);
//            assertResultIds(result, "key4", "key3", "key2", "key1");
//        }

        {
            Query query = new Query();
            query.setRangeCondition("field1", "a", "a");
            QueryResult result = index.performQuery(query);
            assertResultIds(result, "key3", "key2", "key1");
        }
    }

    @Test
    public void testDescendingStringIndexSpecialCases() throws Exception {
        final String INDEX_NAME = "descendingStringIndexSpecialCases";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        indexDef.setIdentifierOrder(Order.DESCENDING);
        StringIndexFieldDefinition fieldDef = indexDef.addStringField("field1");
        fieldDef.setOrder(Order.DESCENDING);
        Index index = indexManager.getIndex(indexDef);

        String[] values = {null, "", "a", "aa", "ab"};
        for (int i = 0; i < values.length; i++) {
            IndexEntry entry = new IndexEntry(indexDef);
            entry.addField("field1", values[i]);
            entry.setIdentifier(Bytes.toBytes("key" + (i + 1)));
            index.addEntry(entry);
        }

        {
            Query query = new Query();
            query.setRangeCondition("field1", Query.MIN_VALUE, Query.MAX_VALUE);
            QueryResult result = index.performQuery(query);
            assertResultIds(result, "key5", "key4", "key3", "key2", "key1");
        }

        {
            Query query = new Query();
            query.setRangeCondition("field1", "a", "a");
            QueryResult result = index.performQuery(query);
            assertResultIds(result, "key5", "key4", "key3");
        }

    }

    @Test
    public void testMultiFieldIndexPrefixSearch() throws Exception {
        final String INDEX_NAME = "multiFieldPrefixSearch";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        indexDef.setIdentifierOrder(Order.DESCENDING);

        indexDef.addStringField("field1").setOrder(Order.DESCENDING);
        indexDef.addStringField("field2").setOrder(Order.DESCENDING);

        Index index = indexManager.getIndex(indexDef);

        {
            IndexEntry entry = new IndexEntry(indexDef);
            entry.addField("field1", "ab");
            entry.addField("field2", "cd");
            entry.setIdentifier(Bytes.toBytes("key1"));
            index.addEntry(entry);
        }

        {
            IndexEntry entry = new IndexEntry(indexDef);
            entry.addField("field1", "abc");
            entry.addField("field2", "d");
            entry.setIdentifier(Bytes.toBytes("key2"));
            index.addEntry(entry);
        }

        {
            Query query = new Query();
            query.setRangeCondition("field1", "ab", "ab");
            QueryResult result = index.performQuery(query);

            assertResultIds(result, "key2", "key1");
        }

        {
            Query query = new Query();
            query.setRangeCondition("field1", "abc", "abc");
            QueryResult result = index.performQuery(query);

            assertResultIds(result, "key2");
        }
    }

    @Test
    public void testData() throws Exception {
        final String INDEX_NAME = "dataIndex";
        IndexManager indexManager = new IndexManager(HBASE_PROXY.getConf());

        IndexDefinition indexDef = new IndexDefinition(INDEX_NAME);
        indexDef.addStringField("field1");
        indexManager.getIndex(indexDef);
        Index index = indexManager.getIndex(INDEX_NAME);

        String[] values = new String[]{"foo", "bar"};

        for (String value : values) {
            IndexEntry entry = new IndexEntry(indexDef);
            entry.addField("field1", value);
            entry.addData(Bytes.toBytes("originalValue"), Bytes.toBytes(value));
            entry.setIdentifier(Bytes.toBytes(value));
            index.addEntry(entry);
        }


        Query query = new Query();
        query.setRangeCondition("field1", Query.MIN_VALUE, Query.MAX_VALUE);
        QueryResult result = index.performQuery(query);

        assertNotNull(result.next());
        assertEquals("bar", result.getDataAsString("originalValue"));

        assertNotNull(result.next());
        assertEquals("foo", result.getDataAsString("originalValue"));
    }

    private void assertResultIds(QueryResult result, String... expectedIdentifiers) throws IOException {
        int resultIdx = 0;
        byte[] identifier;
        while ((identifier = result.next()) != null) {
            if (resultIdx >= expectedIdentifiers.length) {
                fail("Too many query results.");
            }
            assertEquals(expectedIdentifiers[resultIdx], Bytes.toString(identifier));
            resultIdx++;
        }
        assertNull(result.next());
        assertEquals("too little query results", expectedIdentifiers.length, resultIdx);
    }

    private void assertResultSize(int expectedCount, QueryResult result) throws IOException {
        int matchCount = 0;
        while (result.next() != null) {
            matchCount++;
        }
        assertEquals(expectedCount, matchCount);
    }
}
TOP

Related Classes of org.lilyproject.hbaseindex.IndexTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.