Package org.apache.jackrabbit.oak.plugins.index.property

Source Code of org.apache.jackrabbit.oak.plugins.index.property.OrderedPropertyIndexQueryTest

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.jackrabbit.oak.plugins.index.property;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.apache.jackrabbit.JcrConstants.JCR_SYSTEM;
import static org.apache.jackrabbit.JcrConstants.NT_UNSTRUCTURED;
import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_NODE_TYPES;
import static org.junit.Assert.assertNotNull;

import java.text.ParseException;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.jcr.RepositoryException;

import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.PropertyValue;
import org.apache.jackrabbit.oak.api.ResultRow;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
import org.apache.jackrabbit.oak.plugins.index.IndexUpdateProvider;
import org.apache.jackrabbit.oak.plugins.index.IndexUtils;
import org.apache.jackrabbit.oak.plugins.index.property.OrderedIndex.OrderDirection;
import org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState;
import org.apache.jackrabbit.oak.query.QueryEngineSettings;
import org.apache.jackrabbit.oak.query.ast.Operator;
import org.apache.jackrabbit.oak.query.ast.SelectorImpl;
import org.apache.jackrabbit.oak.query.index.FilterImpl;
import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
import org.apache.jackrabbit.oak.spi.commit.EditorHook;
import org.apache.jackrabbit.oak.spi.query.Filter;
import org.apache.jackrabbit.oak.spi.query.PropertyValues;
import org.apache.jackrabbit.oak.spi.query.QueryIndex;
import org.apache.jackrabbit.oak.spi.query.QueryIndex.IndexPlan;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.oak.util.NodeUtil;
import org.junit.Test;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;

public class OrderedPropertyIndexQueryTest extends BasicOrderedPropertyIndexQueryTest {
    private static final EditorHook HOOK = new EditorHook(new IndexUpdateProvider(
        new OrderedPropertyIndexEditorProvider()));

    @Override
    protected void createTestIndexNode() throws Exception {
        Tree index = root.getTree("/");
        IndexUtils.createIndexDefinition(new NodeUtil(index.getChild(IndexConstants.INDEX_DEFINITIONS_NAME)),
            TEST_INDEX_NAME, false, new String[] { ORDERED_PROPERTY }, null, OrderedIndex.TYPE);
        root.commit();
    }

    /**
     * Query the index for retrieving all the entries
     *
     * @throws CommitFailedException
     * @throws ParseException
     * @throws RepositoryException
     */
    @Test
    public void queryAllEntries() throws CommitFailedException, ParseException, RepositoryException {
        setTravesalEnabled(false);

        // index automatically created by the framework:
        // {@code createTestIndexNode()}

        Tree rTree = root.getTree("/");
        Tree test = rTree.addChild("test");
        List<ValuePathTuple> nodes = addChildNodes(generateOrderedValues(NUMBER_OF_NODES), test,
            OrderDirection.ASC, Type.STRING);
        root.commit();

        // querying
        Iterator<? extends ResultRow> results;
        results = executeQuery(String.format("SELECT * from [%s] WHERE foo IS NOT NULL", NT_UNSTRUCTURED), SQL2, null)
            .getRows().iterator();
        assertRightOrder(nodes, results);

        setTravesalEnabled(true);
    }

    /**
     * test the index for returning the items related to a single key
     *
     * @throws CommitFailedException
     * @throws ParseException
     */
    @Test
    public void queryOneKey() throws CommitFailedException, ParseException {
        setTravesalEnabled(false);

        // index automatically created by the framework:
        // {@code createTestIndexNode()}

        Tree rTree = root.getTree("/");
        Tree test = rTree.addChild("test");
        List<ValuePathTuple> nodes = addChildNodes(generateOrderedValues(NUMBER_OF_NODES), test,
            OrderDirection.ASC, Type.STRING);
        root.commit();

        // getting the middle of the random list of nodes.
        ValuePathTuple searchfor = nodes.get(NUMBER_OF_NODES / 2);

        Map<String, PropertyValue> filter = ImmutableMap.of(ORDERED_PROPERTY,
            PropertyValues.newString(searchfor.getValue()));
        String query = "SELECT * FROM [%s] WHERE %s=$%s";
        Iterator<? extends ResultRow> results = executeQuery(
            String.format(query, NT_UNSTRUCTURED, ORDERED_PROPERTY, ORDERED_PROPERTY), SQL2, filter)
            .getRows().iterator();
        assertTrue("one element is expected", results.hasNext());
        assertEquals("wrong path returned", searchfor.getPath(), results.next().getPath());
        assertFalse("there should be not any more items", results.hasNext());

        setTravesalEnabled(true);
    }

    /**
     * test the range query in case of '>' condition
     *
     * @throws CommitFailedException
     * @throws ParseException
     */
    @Test
    public void queryGreaterThan() throws CommitFailedException, ParseException {
        setTravesalEnabled(false);

        final OrderDirection direction = OrderDirection.ASC;
        final String query = "SELECT * FROM [nt:base] AS n WHERE n.%s > $%s";

        // index automatically created by the framework:
        // {@code createTestIndexNode()}

        // initialising the data
        Tree rTree = root.getTree("/");
        Tree test = rTree.addChild("test");
        Calendar start = midnightFirstJan2013();
        List<ValuePathTuple> nodes = addChildNodes(
            generateOrderedDates(NUMBER_OF_NODES, direction, start), test, direction, Type.DATE);
        root.commit();

        Calendar searchForCalendar = (Calendar) start.clone();
        searchForCalendar.add(Calendar.HOUR_OF_DAY, 36);
        String searchFor = ISO_8601_2000.format(searchForCalendar.getTime());
        Map<String, PropertyValue> filter = ImmutableMap.of(ORDERED_PROPERTY,
            PropertyValues.newDate(searchFor));
        Iterator<? extends ResultRow> results = executeQuery(
            String.format(query, ORDERED_PROPERTY, ORDERED_PROPERTY), SQL2, filter).getRows()
            .iterator();
        Iterator<ValuePathTuple> filtered = Iterables.filter(nodes,
            new ValuePathTuple.GreaterThanPredicate(searchFor)).iterator();
        assertRightOrder(Lists.newArrayList(filtered), results);
        assertFalse("We should have looped throuhg all the results", results.hasNext());

        setTravesalEnabled(true);
    }

    /**
     * test the range query in case of '>=' condition
     * @throws CommitFailedException
     * @throws ParseException
     */
    @Test
    public void queryGreaterEqualThan() throws CommitFailedException, ParseException {
        setTravesalEnabled(false);

        final OrderDirection direction = OrderDirection.ASC;
        final String query = "SELECT * FROM [nt:base] AS n WHERE n.%s >= $%s";

        // index automatically created by the framework:
        // {@code createTestIndexNode()}

        // initialising the data
        Tree rTree = root.getTree("/");
        Tree test = rTree.addChild("test");
        Calendar start = midnightFirstJan2013();
        List<ValuePathTuple> nodes = addChildNodes(
            generateOrderedDates(NUMBER_OF_NODES, direction, start), test, direction, Type.DATE);
        root.commit();

        Calendar searchForCalendar = (Calendar) start.clone();
        searchForCalendar.add(Calendar.HOUR_OF_DAY, 36);
        String searchFor = ISO_8601_2000.format(searchForCalendar.getTime());
        Map<String, PropertyValue> filter = ImmutableMap.of(ORDERED_PROPERTY,
            PropertyValues.newDate(searchFor));
        Iterator<? extends ResultRow> results = executeQuery(
            String.format(query, ORDERED_PROPERTY, ORDERED_PROPERTY), SQL2, filter).getRows()
            .iterator();
        Iterator<ValuePathTuple> filtered = Iterables.filter(nodes,
                new ValuePathTuple.GreaterThanPredicate(searchFor, true))
                .iterator();
        assertRightOrder(Lists.newArrayList(filtered), results);
        assertFalse("We should have looped throuhg all the results", results.hasNext());

        setTravesalEnabled(true);
    }

    /**
     * test the range query in case of '<' condition
     *
     * in this case as we're ascending we're expecting an empty resultset with the proper
     * provider. not the lowcost one.
     * @throws Exception
     */
    @Test
    public void queryLessThan() throws Exception {
        initWithProperProvider();
        setTravesalEnabled(false);
        final OrderDirection direction = OrderDirection.DESC;
        final String query = "SELECT * FROM [nt:base] AS n WHERE n.%s < $%s";

        // index automatically created by the framework:
        // {@code createTestIndexNode()}

        // initialising the data
        Tree rTree = root.getTree("/");
        Tree test = rTree.addChild("test");
        Calendar start = midnightFirstJan2013();
        addChildNodes(
            generateOrderedDates(NUMBER_OF_NODES, direction, start), test, direction, Type.DATE);
        root.commit();

        Calendar searchForCalendar = (Calendar) start.clone();
        searchForCalendar.add(Calendar.HOUR_OF_DAY, -36);
        String searchFor = ISO_8601_2000.format(searchForCalendar.getTime());
        Map<String, PropertyValue> filter = ImmutableMap.of(ORDERED_PROPERTY,
            PropertyValues.newDate(searchFor));
        Iterator<? extends ResultRow> results = executeQuery(
            String.format(query, ORDERED_PROPERTY, ORDERED_PROPERTY), SQL2, filter).getRows()
            .iterator();
        assertFalse("We should have no results as of the cost and index direction", results.hasNext());

        setTravesalEnabled(true);
    }

    /**
     * test the range query in case of '<=' condition
     *
     * in this case as we're ascending we're expecting an empty resultset with the proper
     * provider. not the lowcost one.
     * @throws Exception
     */
    @Test
    public void queryLessEqualThan() throws Exception {
        initWithProperProvider();
        initWithProperProvider();
        setTravesalEnabled(false);
        final OrderDirection direction = OrderDirection.DESC;
        final String query = "SELECT * FROM [nt:base] AS n WHERE n.%s <= $%s";

        // index automatically created by the framework:
        // {@code createTestIndexNode()}

        // initialising the data
        Tree rTree = root.getTree("/");
        Tree test = rTree.addChild("test");
        Calendar start = midnightFirstJan2013();
        addChildNodes(
            generateOrderedDates(NUMBER_OF_NODES, direction, start), test, direction, Type.DATE);
        root.commit();

        Calendar searchForCalendar = (Calendar) start.clone();
        searchForCalendar.add(Calendar.HOUR_OF_DAY, -36);
        String searchFor = ISO_8601_2000.format(searchForCalendar.getTime());
        Map<String, PropertyValue> filter = ImmutableMap.of(ORDERED_PROPERTY,
            PropertyValues.newDate(searchFor));
        Iterator<? extends ResultRow> results = executeQuery(
            String.format(query, ORDERED_PROPERTY, ORDERED_PROPERTY), SQL2, filter).getRows()
            .iterator();
        assertFalse("We should have no results as of the cost and index direction", results.hasNext());

        setTravesalEnabled(true);
    }

    @Test
    public void queryAllEntriesWithOrderBy() throws CommitFailedException, ParseException, RepositoryException {
        setTravesalEnabled(false);

        // index automatically created by the framework:
        // {@code createTestIndexNode()}

        Tree rTree = root.getTree("/");
        Tree test = rTree.addChild("test");
        List<ValuePathTuple> nodes = addChildNodes(generateOrderedValues(NUMBER_OF_NODES), test,
            OrderDirection.ASC, Type.STRING);
        root.commit();

        // querying
        Iterator<? extends ResultRow> results;
        String query = String.format(
            "SELECT * from [nt:base] WHERE %s IS NOT NULL ORDER BY %s",
            ORDERED_PROPERTY,
            ORDERED_PROPERTY);
        results = executeQuery(query, SQL2, null)
            .getRows().iterator();
        assertRightOrder(nodes, results);

        setTravesalEnabled(true);
    }

    @Test
    public void orderByQueryNoWhere() throws CommitFailedException, ParseException {
        setTravesalEnabled(false);

        // index automatically created by the framework:
        // {@code createTestIndexNode()}

        Tree rTree = root.getTree("/");
        Tree test = rTree.addChild("test");
        List<ValuePathTuple> nodes = addChildNodes(generateOrderedValues(NUMBER_OF_NODES), test,
            OrderDirection.ASC, Type.STRING);
        root.commit();

        // querying
        Iterator<? extends ResultRow> results;
        String query = String.format(
            "SELECT * from [nt:base] ORDER BY %s",
            ORDERED_PROPERTY);
        results = executeQuery(query, SQL2, null)
            .getRows().iterator();
        assertRightOrder(nodes, results);

        setTravesalEnabled(true);
    }

    @Test
    public void planOderByNoWhere() throws IllegalArgumentException, RepositoryException,
                                   CommitFailedException {

        NodeBuilder root = EmptyNodeState.EMPTY_NODE.builder();

        IndexUtils.createIndexDefinition(root.child(IndexConstants.INDEX_DEFINITIONS_NAME),
            TEST_INDEX_NAME, false, ImmutableList.of(ORDERED_PROPERTY), null, OrderedIndex.TYPE,
            ImmutableMap.<String, String> of());

        NodeState before = root.getNodeState();
        final OrderDirection direction = OrderDirection.ASC;
        final QueryIndex.OrderEntry.Order order = OrderDirection.ASC.equals(direction) ? QueryIndex.OrderEntry.Order.ASCENDING
                                                                                      : QueryIndex.OrderEntry.Order.DESCENDING;

        List<String> values = generateOrderedValues(NUMBER_OF_NODES, direction);
        addChildNodes(values, root, Type.STRING);
        NodeState after = root.getNodeState();

        NodeState indexed = HOOK.processCommit(before, after, CommitInfo.EMPTY);

        final OrderedPropertyIndex index = new OrderedPropertyIndex();
        final String nodeTypeName = JcrConstants.NT_BASE;

        Filter filter = createFilter(indexed, nodeTypeName);

        List<QueryIndex.OrderEntry> sortOrder = ImmutableList.of(createOrderEntry(ORDERED_PROPERTY,
            order));
        List<IndexPlan> plans = index.getPlans(filter, sortOrder, indexed);

        assertNotNull(plans);
        assertEquals(1, plans.size());
        IndexPlan p = plans.get(0);
        assertTrue(p.getEstimatedEntryCount() > 0);
        assertNotNull(p.getSortOrder());
        assertEquals(1, p.getSortOrder().size());
        QueryIndex.OrderEntry oe = p.getSortOrder().get(0);
        assertNotNull(oe);
        assertEquals(ORDERED_PROPERTY, oe.getPropertyName());
        assertEquals(QueryIndex.OrderEntry.Order.ASCENDING, oe.getOrder());
    }

    @Test
    public void queryOrderByNonIndexedProperty() throws CommitFailedException, ParseException {
        setTravesalEnabled(false);

        // index automatically created by the framework:
        // {@code createTestIndexNode()}

        Tree rTree = root.getTree("/");
        Tree test = rTree.addChild("test");
        addChildNodes(generateOrderedValues(NUMBER_OF_NODES), test,
            OrderDirection.ASC, Type.STRING);
        root.commit();

        // querying
        Iterator<? extends ResultRow> results;
        String query = "SELECT * from [nt:base] ORDER BY somethingnotindexed";
        results = executeQuery(query, SQL2, null)
            .getRows().iterator();
        assertFalse("An empty resultset is expected", results.hasNext());

        setTravesalEnabled(true);
    }

    private static FilterImpl createFilter(NodeState indexed, String nodeTypeName) {
        NodeState system = indexed.getChildNode(JCR_SYSTEM);
        NodeState types = system.getChildNode(JCR_NODE_TYPES);
        NodeState type = types.getChildNode(nodeTypeName);
        SelectorImpl selector = new SelectorImpl(type, nodeTypeName);
        return new FilterImpl(selector, "SELECT * FROM [" + nodeTypeName + "]", new QueryEngineSettings());
    }

    private static QueryIndex.OrderEntry createOrderEntry(String property,
                                                          QueryIndex.OrderEntry.Order order) {
        return new QueryIndex.OrderEntry(property, Type.UNDEFINED, order);
    }

    @Test
    public void planOrderByNonIndexedProperty() throws IllegalArgumentException,
                                               RepositoryException, CommitFailedException {
        NodeBuilder root = EmptyNodeState.EMPTY_NODE.builder();

        IndexUtils.createIndexDefinition(root.child(IndexConstants.INDEX_DEFINITIONS_NAME),
            TEST_INDEX_NAME, false, ImmutableList.of(ORDERED_PROPERTY), null, OrderedIndex.TYPE,
            ImmutableMap.<String, String> of());

        NodeState before = root.getNodeState();
        final OrderDirection direction = OrderDirection.ASC;
        final QueryIndex.OrderEntry.Order order = OrderDirection.ASC.equals(direction) ? QueryIndex.OrderEntry.Order.ASCENDING
                                                                                      : QueryIndex.OrderEntry.Order.DESCENDING;
        List<String> values = generateOrderedValues(NUMBER_OF_NODES, direction);
        addChildNodes(values, root, Type.STRING);
        NodeState after = root.getNodeState();

        NodeState indexed = HOOK.processCommit(before, after, CommitInfo.EMPTY);

        final OrderedPropertyIndex index = new OrderedPropertyIndex();
        final String nodeTypeName = JcrConstants.NT_BASE;
        Filter filter = createFilter(indexed, nodeTypeName);

        List<QueryIndex.OrderEntry> sortOrder = ImmutableList.of(createOrderEntry(
            "somethingnotindexed", order));

        List<IndexPlan> plans = index.getPlans(filter, sortOrder, indexed);

        assertNotNull(plans);
        assertEquals(0, plans.size());
    }

    /**
     * tests the output of a plan where the query is asked with where conditions that are not indexed
     * but the ORDER BY are on the indexed property
     *
     * eg: SELECT * FROM [nt:base] WHERE pinned=1 ORDER BY lastModified
     *
     * @throws RepositoryException
     * @throws IllegalArgumentException
     * @throws CommitFailedException
     */
    @Test
    public void planOrderAndWhereMixed() throws IllegalArgumentException, RepositoryException, CommitFailedException {
        NodeBuilder root = EmptyNodeState.EMPTY_NODE.builder();

        IndexUtils.createIndexDefinition(root.child(IndexConstants.INDEX_DEFINITIONS_NAME),
            TEST_INDEX_NAME, false, ImmutableList.of(ORDERED_PROPERTY), null, OrderedIndex.TYPE,
            ImmutableMap.<String, String> of());

        NodeState before = root.getNodeState();
        final OrderDirection direction = OrderDirection.ASC;
        final QueryIndex.OrderEntry.Order order = OrderDirection.ASC.equals(direction) ? QueryIndex.OrderEntry.Order.ASCENDING
                                                                                      : QueryIndex.OrderEntry.Order.DESCENDING;
        List<String> values = generateOrderedValues(NUMBER_OF_NODES, direction);
        addChildNodes(values, root, Type.STRING);
        NodeState after = root.getNodeState();

        NodeState indexed = HOOK.processCommit(before, after, CommitInfo.EMPTY);

        final OrderedPropertyIndex index = new OrderedPropertyIndex();
        final String nodeTypeName = JcrConstants.NT_BASE;
        FilterImpl filter = createFilter(indexed, nodeTypeName);
        filter.restrictProperty("somethingNotIndexed", Operator.EQUAL, PropertyValues.newLong(1L));

        List<QueryIndex.OrderEntry> sortOrder = ImmutableList.of(createOrderEntry(
            ORDERED_PROPERTY, order));

        List<IndexPlan> plans = index.getPlans(filter, sortOrder, indexed);
        assertNotNull(plans);
        assertEquals(1, plans.size());
        IndexPlan p = plans.get(0);
        assertTrue(p.getEstimatedEntryCount() > 0);
        assertNotNull(p.getSortOrder());
        assertEquals(1, p.getSortOrder().size());
        assertEquals(QueryIndex.OrderEntry.Order.ASCENDING, p.getSortOrder()
                .get(0).getOrder());
    }

    /**
     * query the index in case of mixed situation
     *
     * eg: SELECT * FROM [nt:base] WHERE pinned=1 ORDER BY lastModified
     *
     * @throws RepositoryException
     * @throws IllegalArgumentException
     * @throws CommitFailedException
     * @throws ParseException
     */
    @Test
    public void queryOrderAndWhereMixed() throws IllegalArgumentException, RepositoryException, CommitFailedException, ParseException {
        setTravesalEnabled(false);

        // index automatically created by the framework:
        // {@code createTestIndexNode()}

        // initiate the repo with some data
        Tree rTree = root.getTree("/");
        Tree test = rTree.addChild("test");
        List<ValuePathTuple> nodes = addChildNodes(generateOrderedValues(NUMBER_OF_NODES), test,
            OrderDirection.ASC, Type.STRING);
        root.commit();

        String where = "wholetthedogsout";
        String value = "woof-woof-woof-woof";

        // let's set the property that will have to be queried only on 2 nodes
        Tree t = root.getTree(nodes.get(0).getPath());
        t.setProperty(where, value);
        t = root.getTree(nodes.get(1).getPath());
        t.setProperty(where, value);
        root.commit();

        // querying
        Iterator<? extends ResultRow> results;
        String query = String.format(
            "SELECT * from [nt:base] WHERE %s=$%s ORDER BY %s",
            where,
            where,
            ORDERED_PROPERTY
            );
        Map<String, PropertyValue> filter = ImmutableMap.of(
            where, PropertyValues.newString(value)
            );
        results = executeQuery(query, SQL2, filter)
            .getRows().iterator();
        assertTrue(results.hasNext());

        setTravesalEnabled(true);
    }

    /**
     * testing explicitly OAK-1561 use-case
     *
     * @throws CommitFailedException
     * @throws ParseException
     */
    @Test
    public void queryGreaterThenWithCast() throws CommitFailedException, ParseException {

        setTravesalEnabled(false);

        final OrderDirection direction = OrderDirection.ASC;
        final String query = "SELECT * FROM [nt:base] WHERE " + ORDERED_PROPERTY
                             + "> cast('%s' as date)";

        // index automatically created by the framework:
        // {@code createTestIndexNode()}

        // initialising the data
        Tree rTree = root.getTree("/");
        Tree test = rTree.addChild("test");
        Calendar start = midnightFirstJan2013();
        List<ValuePathTuple> nodes = addChildNodes(
            generateOrderedDates(NUMBER_OF_NODES, direction, start), test, direction, Type.DATE);
        root.commit();

        Calendar searchForCalendar = (Calendar) start.clone();
        searchForCalendar.add(Calendar.HOUR_OF_DAY, 36);
        String searchFor = ISO_8601_2000.format(searchForCalendar.getTime());
        Iterator<? extends ResultRow> results = executeQuery(String.format(query, searchFor), SQL2,
            null).getRows().iterator();
        Iterator<ValuePathTuple> filtered = Iterables.filter(nodes,
            new ValuePathTuple.GreaterThanPredicate(searchFor)).iterator();
        assertRightOrder(Lists.newArrayList(filtered), results);
        assertFalse("We should have looped throuhg all the results", results.hasNext());

        setTravesalEnabled(true);

    }

    @Test
    public void queryBetweenNoIncludes() throws Exception {
        setTravesalEnabled(false);

        final OrderDirection direction = OrderDirection.ASC;
        final String query = "SELECT * FROM [nt:base] WHERE " + ORDERED_PROPERTY + "> $start AND "
                             + ORDERED_PROPERTY + " < $end";

        // index automatically created by the framework:
        // {@code createTestIndexNode()}

        // initialising the data
        Tree rTree = root.getTree("/");
        Tree test = rTree.addChild("test");
        Calendar start = midnightFirstJan2013();

        List<ValuePathTuple> nodes = addChildNodes(
            generateOrderedDates(NUMBER_OF_NODES, direction, start), test, direction, Type.DATE);
        root.commit();

        Calendar searchForCalendarStart = (Calendar) start.clone();
        searchForCalendarStart.add(Calendar.HOUR_OF_DAY, 36);
        String searchForStart = ISO_8601_2000.format(searchForCalendarStart.getTime());

        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(ISO_8601_2000.parse(nodes.get(nodes.size() - 1).getValue()));
        endCalendar.add(Calendar.HOUR_OF_DAY, -36);
        String searchForEnd = ISO_8601_2000.format(endCalendar.getTime());

        Map<String, PropertyValue> filter = ImmutableMap.of("start",
            PropertyValues.newDate(searchForStart), "end", PropertyValues.newDate(searchForEnd));
        Iterator<? extends ResultRow> results = executeQuery(query, SQL2, filter).getRows()
            .iterator();

        Iterator<ValuePathTuple> filtered = Iterables.filter(nodes,
            new ValuePathTuple.BetweenPredicate(searchForStart, searchForEnd, false, false))
            .iterator();

        assertRightOrder(Lists.newArrayList(filtered), results);
        assertFalse("We should have looped throuhg all the results", results.hasNext());

        setTravesalEnabled(true);

    }

    @Test
    public void queryBetweenIncludeLower() throws Exception {
        setTravesalEnabled(false);

        final OrderDirection direction = OrderDirection.ASC;
        final String query = "SELECT * FROM [nt:base] WHERE " + ORDERED_PROPERTY + ">= $start AND "
                             + ORDERED_PROPERTY + " < $end";

        // index automatically created by the framework:
        // {@code createTestIndexNode()}

        // initialising the data
        Tree rTree = root.getTree("/");
        Tree test = rTree.addChild("test");
        Calendar start = midnightFirstJan2013();

        List<ValuePathTuple> nodes = addChildNodes(
            generateOrderedDates(NUMBER_OF_NODES, direction, start), test, direction, Type.DATE);
        root.commit();

        Calendar searchForCalendarStart = (Calendar) start.clone();
        searchForCalendarStart.add(Calendar.HOUR_OF_DAY, 36);
        String searchForStart = ISO_8601_2000.format(searchForCalendarStart.getTime());

        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(ISO_8601_2000.parse(nodes.get(nodes.size() - 1).getValue()));
        endCalendar.add(Calendar.HOUR_OF_DAY, -36);
        String searchForEnd = ISO_8601_2000.format(endCalendar.getTime());

        Map<String, PropertyValue> filter = ImmutableMap.of("start",
            PropertyValues.newDate(searchForStart), "end", PropertyValues.newDate(searchForEnd));
        Iterator<? extends ResultRow> results = executeQuery(query, SQL2, filter).getRows()
            .iterator();

        Iterator<ValuePathTuple> filtered = Iterables.filter(nodes,
            new ValuePathTuple.BetweenPredicate(searchForStart, searchForEnd, true, false))
            .iterator();

        assertRightOrder(Lists.newArrayList(filtered), results);
        assertFalse("We should have looped throuhg all the results", results.hasNext());

        setTravesalEnabled(true);

    }
   
    @Test
    public void queryBetweenIncludeHigher() throws Exception {
        setTravesalEnabled(false);

        final OrderDirection direction = OrderDirection.ASC;
        final String query = "SELECT * FROM [nt:base] WHERE " + ORDERED_PROPERTY + "> $start AND "
                             + ORDERED_PROPERTY + " <= $end";

        // index automatically created by the framework:
        // {@code createTestIndexNode()}

        // initialising the data
        Tree rTree = root.getTree("/");
        Tree test = rTree.addChild("test");
        Calendar start = midnightFirstJan2013();

        List<ValuePathTuple> nodes = addChildNodes(
            generateOrderedDates(10, direction, start), test, direction, Type.DATE);
        root.commit();

        for (ValuePathTuple n : nodes) {
            n.toString();
            // System.out.println("+++" + n);
        }
       
        Calendar searchForCalendarStart = (Calendar) start.clone();
        searchForCalendarStart.add(Calendar.HOUR_OF_DAY, 36);
        String searchForStart = ISO_8601_2000.format(searchForCalendarStart.getTime());

        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(ISO_8601_2000.parse(nodes.get(nodes.size() - 1).getValue()));
        endCalendar.add(Calendar.HOUR_OF_DAY, -36);
        String searchForEnd = ISO_8601_2000.format(endCalendar.getTime());

        Map<String, PropertyValue> filter = ImmutableMap.of("start",
            PropertyValues.newDate(searchForStart), "end", PropertyValues.newDate(searchForEnd));
        Iterator<? extends ResultRow> results = executeQuery(query, SQL2, filter).getRows()
            .iterator();

        Iterator<ValuePathTuple> filtered = Iterables.filter(nodes,
            new ValuePathTuple.BetweenPredicate(searchForStart, searchForEnd, false, true))
            .iterator();

        while (filtered.hasNext()) {
            System.out.println("---" + filtered.next());
        }
        filtered = Iterables.filter(nodes,
            new ValuePathTuple.BetweenPredicate(searchForStart, searchForEnd, false, true))
            .iterator();
       
        assertRightOrder(Lists.newArrayList(filtered), results);
        assertFalse("We should have looped throuhg all the results", results.hasNext());

        setTravesalEnabled(true);

    }

    @Test
    public void queryBetweenIncludeBoth() throws Exception {
        setTravesalEnabled(false);

        final OrderDirection direction = OrderDirection.ASC;
        final String query = "SELECT * FROM [nt:base] WHERE " + ORDERED_PROPERTY + ">= $start AND "
                             + ORDERED_PROPERTY + " <= $end";

        // index automatically created by the framework:
        // {@code createTestIndexNode()}

        // initialising the data
        Tree rTree = root.getTree("/");
        Tree test = rTree.addChild("test");
        Calendar start = midnightFirstJan2013();

        List<ValuePathTuple> nodes = addChildNodes(
            generateOrderedDates(10, direction, start), test, direction, Type.DATE);
        root.commit();

        for (ValuePathTuple n : nodes) {
            n.toString();
            // System.out.println("+++" + n);
        }
       
        Calendar searchForCalendarStart = (Calendar) start.clone();
        searchForCalendarStart.add(Calendar.HOUR_OF_DAY, 36);
        String searchForStart = ISO_8601_2000.format(searchForCalendarStart.getTime());

        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(ISO_8601_2000.parse(nodes.get(nodes.size() - 1).getValue()));
        endCalendar.add(Calendar.HOUR_OF_DAY, -36);
        String searchForEnd = ISO_8601_2000.format(endCalendar.getTime());

        Map<String, PropertyValue> filter = ImmutableMap.of("start",
            PropertyValues.newDate(searchForStart), "end", PropertyValues.newDate(searchForEnd));
        Iterator<? extends ResultRow> results = executeQuery(query, SQL2, filter).getRows()
            .iterator();

        Iterator<ValuePathTuple> filtered = Iterables.filter(nodes,
            new ValuePathTuple.BetweenPredicate(searchForStart, searchForEnd, false, true))
            .iterator();

        while (filtered.hasNext()) {
            System.out.println("---" + filtered.next());
        }
        filtered = Iterables.filter(nodes,
            new ValuePathTuple.BetweenPredicate(searchForStart, searchForEnd, true, true))
            .iterator();
       
        assertRightOrder(Lists.newArrayList(filtered), results);
        assertFalse("We should have looped throuhg all the results", results.hasNext());

        setTravesalEnabled(true);

    }
}
TOP

Related Classes of org.apache.jackrabbit.oak.plugins.index.property.OrderedPropertyIndexQueryTest

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.