Package org.voltdb.planner

Source Code of org.voltdb.planner.TestIndexReverseScan

/* This file is part of VoltDB.
* Copyright (C) 2008-2014 VoltDB Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/

package org.voltdb.planner;

import org.voltdb.expressions.ExpressionUtil;
import org.voltdb.plannodes.AbstractPlanNode;
import org.voltdb.plannodes.IndexScanPlanNode;
import org.voltdb.plannodes.OrderByPlanNode;
import org.voltdb.plannodes.ProjectionPlanNode;
import org.voltdb.plannodes.SendPlanNode;
import org.voltdb.types.ExpressionType;
import org.voltdb.types.IndexLookupType;
import org.voltdb.types.SortDirectionType;

public class TestIndexReverseScan extends PlannerTestCase {
    @Override
    protected void setUp() throws Exception {
        final boolean planForSinglePartition = true;
        setupSchema(TestIndexReverseScan.class.getResource("testplans-indexvshash-ddl.sql"),
                    "testindexvshashplans", planForSinglePartition);
    }

    @Override
    protected void tearDown() throws Exception {
        super.tearDown();
    }
    String sql;


    public void testLegancyTests()
    {
        sql = "select a from t where a = ? and b < ?";
        checkReverseScan("COVER2_TREE", IndexLookupType.LT, 2, 1, 1, SortDirectionType.INVALID);

        sql = "select a from t where a = ? and b <= ?";
        checkReverseScan("COVER2_TREE", IndexLookupType.LTE, 2, 1, 1, SortDirectionType.INVALID);

        sql = "select a from t where a = ? and c = ? and b < ?;";
        checkReverseScan("COVER3_TREE", IndexLookupType.LT, 3, 2, 1, SortDirectionType.INVALID);

        sql = "select a from t where a = ? and c = ? and b <= ?";
        checkReverseScan("COVER3_TREE", IndexLookupType.LTE, 3, 2, 1, SortDirectionType.INVALID);

        // no ORDER BY node because order-by is handled by index scan inherent ordering
        sql = "select a, b from t where a = ? and c = ? and b < ? order by b desc;";
        checkReverseScan("COVER3_TREE", IndexLookupType.LT, 3, 2, 1, SortDirectionType.DESC);

        sql = "select a, b from t where a = ? and b = ? and c < ? order by c desc;";
        checkReverseScan("IDX_1_TREE", IndexLookupType.LT, 3, 2, 1, SortDirectionType.DESC);

        sql = "select a, b from t where a = ? and c = ? and b <= ? order by b desc;";
        checkReverseScan("COVER3_TREE", IndexLookupType.LTE, 3, 2, 1, SortDirectionType.DESC);

    }

    public void testLegancyTests_NonOptimizable()
    {
        // ORDER BY ASC: do not do reverse scan optimization
        sql = "select a, b from t where a = ? and c = ? and b < ? order by b;";
        checkForwardScan("COVER3_TREE", IndexLookupType.GTE, 2, 3, 0, SortDirectionType.ASC);

        // ORDER BY ASC: do not do reverse scan optimization
        sql = "select a, b from t where a = ? and c = ? and b <= ? order by b;";
        checkForwardScan("COVER3_TREE", IndexLookupType.GTE, 2, 3, 0, SortDirectionType.ASC);
    }

    public void testENG5297()
    {
        sql = "SELECT * FROM data_reports " +
                "WHERE appID = 1486287933647372287 AND reportID = 1526804868369481731 " +
                "AND metricID = 1486287935375409155 AND field = 'accountID' " +
                "AND time >= '2013-09-29 00:00:00' AND time <= '2013-10-07 00:00:00' " +
                "ORDER BY time DESC LIMIT 150";

        checkReverseScan("ASSUMEUNIQUE_PK_INDEX", IndexLookupType.LTE, 3, 3, 2, SortDirectionType.DESC);
    }

    public void testNonOptimizable()
    {
        // One column index cases.
        sql = "select * from R where a >= 1 AND a <= 9 ORDER BY b DESC";
        // Current code logic: if still needs order by node, the sort direction is Invalid.
        checkForwardScan("R1_TREE", IndexLookupType.GTE, 1, 1, 0, SortDirectionType.INVALID, true);

        // Have one extra post predicate because of ENG-3913. ???
        sql = "select * from R where a > 1 ORDER BY b desc";
        checkForwardScan("R1_TREE", IndexLookupType.GT, 1, 0, 0, SortDirectionType.INVALID, true);

        sql = "select * from R where a >= 1 ORDER BY b desc";
        checkForwardScan("R1_TREE", IndexLookupType.GTE, 1, 0, 0, SortDirectionType.INVALID, true);

        // Two columns index cases.
        sql = "select * from R where b = 1 ORDER BY c";
        checkForwardScan("R2_TREE", IndexLookupType.GTE, 1, 1, 0, SortDirectionType.ASC);

        sql = "select * from R where b > 1 ORDER BY c desc";
        checkForwardScan("R2_TREE", IndexLookupType.GT, 1, 0, 1, SortDirectionType.INVALID, true);

        sql = "select * from R where b >= 1 ORDER BY c desc";
        checkForwardScan("R2_TREE", IndexLookupType.GTE, 1, 0, 0, SortDirectionType.INVALID, true);


        // Three columns index cases.
        sql = "select * from R where d = 1 AND e > 2 ORDER BY d desc, e desc, f asc";
        checkForwardScan("R3_TREE", IndexLookupType.GT, 2, 1, 1, SortDirectionType.INVALID, true);

        sql = "select * from R where d = 1 AND e > 2 ORDER BY e asc, f asc";
        checkForwardScan("R3_TREE", IndexLookupType.GT, 2, 1, 1, SortDirectionType.ASC);
    }

    public void testOneColumnIndex()
    {
        sql = "select * from R where a < 9";
        checkReverseScan("R1_TREE", IndexLookupType.LT, 1, 0, 1, SortDirectionType.INVALID);

        sql = "select * from R where a <= 9";
        checkReverseScan("R1_TREE", IndexLookupType.LTE, 1, 0, 1, SortDirectionType.INVALID);

        // Have one extra post predicate because of ENG-3913.
        sql = "select * from R where a > 1 ORDER BY a desc";
        checkReverseScan("R1_TREE", IndexLookupType.GT, 0, 1, 1, false, SortDirectionType.DESC);

        sql = "select * from R where a >= 1 ORDER BY a desc";
        checkReverseScan("R1_TREE", IndexLookupType.GTE, 0, 1, 0, SortDirectionType.DESC);

        sql = "select * from R where a > 1 AND a < 9 ORDER BY a desc";
        checkReverseScan("R1_TREE", IndexLookupType.LT, 1, 1, 0, SortDirectionType.DESC);

        sql = "select * from R where a > 1 AND a <= 9 ORDER BY a desc";
        checkReverseScan("R1_TREE", IndexLookupType.LTE, 1, 1, 0, SortDirectionType.DESC);

        sql = "select * from R where a >= 1 AND a < 9 ORDER BY a desc";
        checkReverseScan("R1_TREE", IndexLookupType.LT, 1, 1, 0, SortDirectionType.DESC);

        sql = "select * from R where a >= 1 AND a <= 9 ORDER BY a desc";
        checkReverseScan("R1_TREE", IndexLookupType.LTE, 1, 1, 0, SortDirectionType.DESC);
    }


    // All forward scan cases should be supported in future by using the reverse scan check.
    public void testTwoColumnsIndex()
    {
        // Case 1: first column equal
        // [Unsupported cases]:
//        sql = "select * from R where b = 1 ORDER BY c desc";
//        checkReverseScan("R2_TREE", IndexLookupType.LTE, 1, 1, 0, SortDirectionType.DESC);

        sql = "select * from R where b = 1 AND c < 2 ORDER BY c desc";
        checkReverseScan("R2_TREE", IndexLookupType.LT, 2, 1, 1, SortDirectionType.DESC);

        sql = "select * from R where b = 1 AND c <= 2 ORDER BY c desc";
        checkReverseScan("R2_TREE", IndexLookupType.LTE, 2, 1, 1, SortDirectionType.DESC);

        // Switch the next few GT, GTE test cases to use reverse scan feature.

        // [Unsupported cases]:
//        sql = "select * from R where b = 1 AND C > 3 ORDER BY c desc";
//        checkReverseScan("R2_TREE", IndexLookupType.GT, 1, 2, 1, SortDirectionType.DESC);
//        sql = "select * from R where b = 1 AND C >= 3 ORDER BY c desc";
//        checkReverseScan("R2_TREE", IndexLookupType.GTE, 1, 2, 0, SortDirectionType.DESC);

        // Test between.
        sql = "select * from R where b = 1 AND C > 3 AND C < 6 ORDER BY c desc";
        checkReverseScan("R2_TREE", IndexLookupType.LT, 2, 2, 0, SortDirectionType.DESC);

        sql = "select * from R where b = 1 AND C > 3 AND C <= 6 ORDER BY c desc";
        checkReverseScan("R2_TREE", IndexLookupType.LTE, 2, 2, 0, SortDirectionType.DESC);

        sql = "select * from R where b = 1 AND C >= 3 AND C < 6 ORDER BY c desc";
        checkReverseScan("R2_TREE", IndexLookupType.LT, 2, 2, 0, SortDirectionType.DESC);

        sql = "select * from R where b = 1 AND C >= 3 AND C <= 6 ORDER BY c desc";
        checkReverseScan("R2_TREE", IndexLookupType.LTE, 2, 2, 0, SortDirectionType.DESC);


        // Case 2: first column less than
        sql = "select * from R where b < 1 ORDER BY b desc";
        checkReverseScan("R2_TREE", IndexLookupType.LT, 1, 0, 1, SortDirectionType.DESC);

        sql = "select * from R where b <= 1 ORDER BY b desc";
        checkReverseScan("R2_TREE", IndexLookupType.LTE, 1, 0, 1, SortDirectionType.DESC);

        // The second column filter will be a post predicate, does not need to test all cases for the second column.
        sql = "select * from R where b <= 1 AND c < 2 ORDER BY b desc";
        checkReverseScan("R2_TREE", IndexLookupType.LTE, 1, 0, 2, SortDirectionType.DESC);

        sql = "select * from R where b < 1 AND c < 2 ORDER BY b desc";
        checkReverseScan("R2_TREE", IndexLookupType.LT, 1, 0, 2, SortDirectionType.DESC);

        sql = "select * from R where b <= 1 AND c <= 2 ORDER BY b desc";
        checkReverseScan("R2_TREE", IndexLookupType.LTE, 1, 0, 2, SortDirectionType.DESC);

        sql = "select * from R where b < 1 AND c <= 2 ORDER BY b desc";
        checkReverseScan("R2_TREE", IndexLookupType.LT, 1, 0, 2, SortDirectionType.DESC);

        sql = "select * from R where b < 1 AND c = 2 ORDER BY b desc";
        checkReverseScan("R2_TREE", IndexLookupType.LT, 1, 0, 2, SortDirectionType.DESC);

        sql = "select * from R where b <= 1 AND c = 2 ORDER BY b desc";
        checkReverseScan("R2_TREE", IndexLookupType.LTE, 1, 0, 2, SortDirectionType.DESC);

        // Order by the second column will not remove the order by node.
        sql = "select * from R where b < 1 ORDER BY c desc";
        checkReverseScan("R2_TREE", IndexLookupType.LT, 1, 0, 1, 1, false, SortDirectionType.INVALID, true);

        sql = "select * from R where b <= 1 ORDER BY c desc";
        checkReverseScan("R2_TREE", IndexLookupType.LTE, 1, 0, 1, 1, false, SortDirectionType.INVALID, true);

        sql = "select * from R where b <= 1 AND c < 2 ORDER BY c desc";
        checkReverseScan("R2_TREE", IndexLookupType.LTE, 1, 0, 2, 1, false, SortDirectionType.INVALID, true);

        // The second column filter will be a post predicate, does not need to test all cases for the second column.
        sql = "select * from R where b < 1 AND c < 2 ORDER BY c desc";
        checkReverseScan("R2_TREE", IndexLookupType.LT, 1, 0, 2, 1, false, SortDirectionType.INVALID, true);

        sql = "select * from R where b <= 1 AND c < 2 ORDER BY c desc";
        checkReverseScan("R2_TREE", IndexLookupType.LTE, 1, 0, 2, 1, false, SortDirectionType.INVALID, true);
        // ...


        // Case 3: first column greater than
        // Have one extra post predicate because of ENG-3913.
        sql = "select * from R where b > 1 ORDER BY b desc";
        checkReverseScan("R2_TREE", IndexLookupType.GT, 0, 1, 1, false, SortDirectionType.DESC);

        sql = "select * from R where b >= 1 ORDER BY b desc";
        checkReverseScan("R2_TREE", IndexLookupType.GTE, 0, 1, 0, SortDirectionType.DESC);

        // The second column filter will be a post predicate, does not need to test all permutations.
        sql = "select * from R where b > 1 AND c > 2 ORDER BY b desc";
        checkReverseScan("R2_TREE", IndexLookupType.GT, 0, 1, 2, false, SortDirectionType.DESC);

        sql = "select * from R where b >= 1 AND c > 2 ORDER BY b desc";
        checkReverseScan("R2_TREE", IndexLookupType.GTE, 0, 1, 1, false, SortDirectionType.DESC);

        sql = "select * from R where b > 1 AND c = 2 ORDER BY b desc";
        checkReverseScan("R2_TREE", IndexLookupType.GT, 0, 1, 2, false, SortDirectionType.DESC);

        sql = "select * from R where b >= 1 AND c = 2 ORDER BY b desc";
        checkReverseScan("R2_TREE", IndexLookupType.GTE, 0, 1, 1, false, SortDirectionType.DESC);
        // ...
    }

    public void testThreeColumnsIndex()
    {

        sql = "select * from R where d = 1 AND e < 2 ORDER BY e desc";
        checkReverseScan("R3_TREE", IndexLookupType.LT, 2, 1, 1, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e <= 2 ORDER BY e desc";
        checkReverseScan("R3_TREE", IndexLookupType.LTE, 2, 1, 1, SortDirectionType.DESC);

        // Test bettween with different order by.
        sql = "select * from R where d = 1 AND e > 2 AND e < 10 ORDER BY e desc";
        checkReverseScan("R3_TREE", IndexLookupType.LT, 2, 2, 0, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e > 2 AND e <= 10 ORDER BY e desc";
        checkReverseScan("R3_TREE", IndexLookupType.LTE, 2, 2, 0, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e >= 2 AND e < 10 ORDER BY e desc";
        checkReverseScan("R3_TREE", IndexLookupType.LT, 2, 2, 0, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e >= 2 AND e <= 10 ORDER BY e desc";
        checkReverseScan("R3_TREE", IndexLookupType.LTE, 2, 2, 0, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e > 2 AND e < 10 ORDER BY e desc, f desc";
        checkReverseScan("R3_TREE", IndexLookupType.LT, 2, 2, 0, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e > 2 AND e <= 10 ORDER BY e desc, f desc";
        checkReverseScan("R3_TREE", IndexLookupType.LTE, 2, 2, 0, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e >= 2 AND e < 10 ORDER BY e desc, f desc";
        checkReverseScan("R3_TREE", IndexLookupType.LT, 2, 2, 0, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e >= 2 AND e <= 10 ORDER BY e desc, f desc";
        checkReverseScan("R3_TREE", IndexLookupType.LTE, 2, 2, 0, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e > 2 AND e < 10 ORDER BY d desc, e desc, f desc";
        checkReverseScan("R3_TREE", IndexLookupType.LT, 2, 2, 0, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e > 2 AND e <= 10 ORDER BY d desc, e desc, f desc";
        checkReverseScan("R3_TREE", IndexLookupType.LTE, 2, 2, 0, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e >= 2 AND e < 10 ORDER BY d desc, e desc, f desc";
        checkReverseScan("R3_TREE", IndexLookupType.LT, 2, 2, 0, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e >= 2 AND e <= 10 ORDER BY d desc, e desc, f desc";
        checkReverseScan("R3_TREE", IndexLookupType.LTE, 2, 2, 0, SortDirectionType.DESC);


        // Test adding post filters.
        // The third column filter will be a post predicate, does not need to test all permutations.
        sql = "select * from R where d = 1 AND e > 2 AND e < 10 AND f = 5 ORDER BY e desc";
        checkReverseScan("R3_TREE", IndexLookupType.LT, 2, 2, 1, false, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e > 2 AND e <= 10 AND f = 5 ORDER BY e desc";
        checkReverseScan("R3_TREE", IndexLookupType.LTE, 2, 2, 1, false, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e >= 2 AND e < 10 AND f = 5 ORDER BY e desc";
        checkReverseScan("R3_TREE", IndexLookupType.LT, 2, 2, 1, false, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e >= 2 AND e <= 10 AND f = 5 ORDER BY e desc";
        checkReverseScan("R3_TREE", IndexLookupType.LTE, 2, 2, 1, false, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e > 2 AND e < 10 AND f >= 5 ORDER BY e desc";
        checkReverseScan("R3_TREE", IndexLookupType.LT, 2, 2, 1, false, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e > 2 AND e <= 10 AND f <= 5 ORDER BY e desc";
        checkReverseScan("R3_TREE", IndexLookupType.LTE, 2, 2, 1, false, SortDirectionType.DESC);

        // Add one more order by.
        sql = "select * from R where d = 1 AND e > 2 AND e < 10 AND f = 5 ORDER BY e desc, f desc";
        checkReverseScan("R3_TREE", IndexLookupType.LT, 2, 2, 1, false, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e > 2 AND e <= 10 AND f = 5 ORDER BY e desc, f desc";
        checkReverseScan("R3_TREE", IndexLookupType.LTE, 2, 2, 1, false, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e >= 2 AND e < 10 AND f = 5 ORDER BY e desc, f desc";
        checkReverseScan("R3_TREE", IndexLookupType.LT, 2, 2, 1, false, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e >= 2 AND e <= 10 AND f = 5 ORDER BY e desc, f desc";
        checkReverseScan("R3_TREE", IndexLookupType.LTE, 2, 2, 1, false, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e > 2 AND e < 10 AND f >= 5 ORDER BY e desc, f desc";
        checkReverseScan("R3_TREE", IndexLookupType.LT, 2, 2, 1, false, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e > 2 AND e <= 10 AND f <= 5 ORDER BY e desc, f desc";
        checkReverseScan("R3_TREE", IndexLookupType.LTE, 2, 2, 1, false, SortDirectionType.DESC);


        // [Unsupported cases]:
//        sql = "select * from R where d = 1 ORDER BY e desc, f desc";
//        checkForwardScan("R3_TREE", IndexLookupType.GTE, 1, 1, 0, SortDirectionType.INVALID, true);
//        sql = "select * from R where d = 1 AND e > 2 ORDER BY e desc";
//        checkReverseScan("R3_TREE", IndexLookupType.GT, 1, 2, 1, SortDirectionType.DESC);
//        sql = "select * from R where d = 1 AND e >= 2 ORDER BY d desc, e desc";
//        checkReverseScan("R3_TREE", IndexLookupType.GTE, 1, 2, 1, SortDirectionType.DESC);
//        sql = "select * from R where d = 1 AND e > 2 AND f = 5 ORDER BY e desc";
//        checkReverseScan("R3_TREE", IndexLookupType.GT, 1, 2, 2, SortDirectionType.DESC);
//        sql = "select * from R where d = 1 AND e >= 2 AND f = 5 ORDER BY e desc";
//        checkReverseScan("R3_TREE", IndexLookupType.GTE, 1, 2, 1, SortDirectionType.DESC);

    }

    public void test_useless__orderby_confuses_planner()
    {
        // (1) In future, using forward scan.
        // useless prefix order by.
        sql = "select * from R where d = 1 AND e > 2 ORDER BY d desc, e asc, f asc";
        checkForwardScan("R3_TREE", IndexLookupType.GT, 2, 1, 1, SortDirectionType.INVALID, true);

        sql = "select * from R where d = 1 AND e > 2 AND f = 4 ORDER BY d desc, e asc, f asc";
        checkForwardScan("R3_TREE", IndexLookupType.GT, 2, 1, 2, SortDirectionType.INVALID, true);

        // useless post order by.
        sql = "select * from R where d = 1 AND e > 2 AND f = 4 ORDER BY e asc, f desc";
        checkForwardScan("R3_TREE", IndexLookupType.GT, 2, 1, 2, SortDirectionType.INVALID, true);


        // (2) In future, using reverse scan.
        // useless prefix order by.
        sql = "select * from R where d = 1 AND e > 2 ORDER BY d desc, e desc, f desc";
        checkForwardScan("R3_TREE", IndexLookupType.GT, 2, 1, 1, SortDirectionType.INVALID, true);

        sql = "select * from R where d = 1 AND e > 2 ORDER BY d asc, e desc, f desc";
        checkForwardScan("R3_TREE", IndexLookupType.GT, 2, 1, 1, SortDirectionType.INVALID, true);


        sql = "select * from R where d = 1 AND e > 2 AND e < 10 ORDER BY d asc, e desc, f desc";
        checkForwardScan("R3_TREE", IndexLookupType.GT, 2, 2, 1, SortDirectionType.INVALID, true);


        sql = "select * from R where d = 1 AND e > 2 AND f = 5 ORDER BY d desc, e desc, f asc";
        checkForwardScan("R3_TREE", IndexLookupType.GT, 2, 1, 2, SortDirectionType.INVALID, true);

        sql = "select * from R where d = 1 AND e > 2 AND f = 5 ORDER BY d asc, e desc, f asc";
        checkForwardScan("R3_TREE", IndexLookupType.GT, 2, 1, 2, SortDirectionType.INVALID, true);

        sql = "select * from R where d = 1 AND e >= 2 AND e <= 10 AND f = 5 ORDER BY d desc, e desc, f asc";
        checkForwardScan("R3_TREE", IndexLookupType.GTE, 2, 2, 1, SortDirectionType.INVALID, true);

        // useless post order by.
        sql = "select * from R where d = 1 AND e > 2 AND f = 5 ORDER BY e desc, f asc";
        checkForwardScan("R3_TREE", IndexLookupType.GT, 2, 1, 2, SortDirectionType.INVALID, true);

        sql = "select * from R where d = 1 AND e > 2 AND f = 5 ORDER BY e desc, f asc";
        checkForwardScan("R3_TREE", IndexLookupType.GT, 2, 1, 2, SortDirectionType.INVALID, true);

        sql = "select * from R where d = 1 AND e >= 2 AND e <= 10 AND f = 5 ORDER BY e desc, f asc";
        checkForwardScan("R3_TREE", IndexLookupType.GTE, 2, 2, 1, SortDirectionType.INVALID, true);
    }

    public void testTry()
    {
        sql = "select * from R where a > 9 order by a desc";
        checkReverseScan("R1_TREE", IndexLookupType.GT, 0, 1, 1, false, SortDirectionType.DESC);
    }


    // [Unsupported cases, but needs to be supported in future] ?
    // Remove these test cases when we support them in future. But remember to turn them on in 2, 3 columns tests.
    public void test_not_supported_cases_waitinglist() {

        // (2) Two columns index cases.
        sql = "select * from R where b = 1 ORDER BY c desc";
        checkForwardScan("R2_TREE", IndexLookupType.GTE, 1, 1, 0, SortDirectionType.INVALID, true);

        sql = "select * from R where b = 1 AND C > 3 ORDER BY c desc";
        checkForwardScan("R2_TREE", IndexLookupType.GT, 2, 1, 0, SortDirectionType.INVALID, true);
        // Have one extra post predicate because of ENG-3913.
        //checkReverseScan("R2_TREE", IndexLookupType.GT, 1, 2, 1, SortDirectionType.DESC);
        sql = "select * from R where b = 1 AND C >= 3 ORDER BY c desc";
        checkForwardScan("R2_TREE", IndexLookupType.GTE, 2, 1, 0, SortDirectionType.INVALID, true);
        //checkReverseScan("R2_TREE", IndexLookupType.GTE, 1, 2, 0, SortDirectionType.DESC);


        // (3) Three columns index cases.

        sql = "select * from R where d = 1 ORDER BY e desc, f desc";
        checkForwardScan("R3_TREE", IndexLookupType.GTE, 1, 1, 0, SortDirectionType.INVALID, true);

        sql = "select * from R where d = 1 AND e > 2 ORDER BY e desc";
        // Have one extra post predicate because of ENG-3913.
        checkForwardScan("R3_TREE", IndexLookupType.GT, 2, 1, 1, SortDirectionType.INVALID, true);
        //checkReverseScan("R3_TREE", IndexLookupType.GT, 1, 2, 1, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e >= 2 ORDER BY d desc, e desc";
        checkForwardScan("R3_TREE", IndexLookupType.GTE, 2, 1, 0, SortDirectionType.INVALID, true);
        //checkReverseScan("R3_TREE", IndexLookupType.GTE, 1, 2, 1, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e > 2 AND f = 5 ORDER BY e desc";
        checkForwardScan("R3_TREE", IndexLookupType.GT, 2, 1, 2, SortDirectionType.INVALID, true);
        //checkReverseScan("R3_TREE", IndexLookupType.GT, 1, 2, 2, SortDirectionType.DESC);

        sql = "select * from R where d = 1 AND e >= 2 AND f = 5 ORDER BY e desc";
        checkForwardScan("R3_TREE", IndexLookupType.GTE, 2, 1, 1, SortDirectionType.INVALID, true);
        //checkReverseScan("R3_TREE", IndexLookupType.GTE, 1, 2, 1, SortDirectionType.DESC);
    }

    private void checkReverseScan(String indexName, IndexLookupType lookupType,
            int searchKeys, int endKeys, int predicates, SortDirectionType sortType) {

        checkReverseScan(indexName, lookupType, searchKeys, endKeys, predicates,
                searchKeys, true, sortType, false);
    }

    private void checkReverseScan(String indexName, IndexLookupType lookupType,
            int searchKeys, int endKeys, int predicates, boolean artificial,
            SortDirectionType sortType) {

        checkReverseScan(indexName, lookupType, searchKeys, endKeys, predicates,
                searchKeys, artificial, sortType, false);
    }


    private void checkReverseScan(String indexName, IndexLookupType lookupType,
            int searchKeys, int endKeys, int predicates, int initials, boolean artificial,
            SortDirectionType sortType, boolean needOrderby) {

        AbstractPlanNode pn = compile(sql);
        System.out.println(pn.toExplainPlanString());

        assertTrue(pn instanceof SendPlanNode);
        pn = pn.getChild(0);
        if (needOrderby) {
            assertTrue(pn instanceof ProjectionPlanNode);
            pn = pn.getChild(0);
            assertTrue(pn instanceof OrderByPlanNode);
            pn = pn.getChild(0);
        }
        assertTrue(pn instanceof IndexScanPlanNode);

        IndexScanPlanNode ispn = (IndexScanPlanNode)pn;
        assertTrue(ispn.getTargetIndexName().contains(indexName));
        assertEquals(lookupType, ispn.getLookupType());
        assertEquals(searchKeys, ispn.getSearchKeyExpressions().size());
        assertEquals(endKeys, ExpressionUtil.uncombine(ispn.getEndExpression()).size());
        assertEquals(predicates, ExpressionUtil.uncombine(ispn.getPredicate()).size());

        assertEquals(initials, ExpressionUtil.uncombine(ispn.getInitialExpression()).size());

        // Test artificial post predicate
        if (predicates == 1 && artificial) {
            assertTrue(ispn.getPredicate().getExpressionType() == ExpressionType.OPERATOR_NOT);
            assertTrue(ispn.getPredicate().getLeft().getExpressionType() == ExpressionType.OPERATOR_IS_NULL);
        } else if (predicates > 1) {
            assertTrue(ispn.getPredicate().getExpressionType() == ExpressionType.CONJUNCTION_AND);
        }

        // SortDirection can be INVALID because we use LookupType to determine
        // index scan direction instead in EE.
        assertEquals(sortType, ispn.getSortDirection());
    }



    private void checkForwardScan(String indexName, IndexLookupType lookupType,
            int searchKeys, int endKeys, int predicates, SortDirectionType sortType) {
        checkForwardScan(indexName, lookupType, searchKeys, endKeys, predicates, sortType, false);
    }

    private void checkForwardScan(String indexName, IndexLookupType lookupType,
            int searchKeys, int endKeys, int predicates, SortDirectionType sortType, boolean needOrderby) {
        AbstractPlanNode pn = compile(sql);
        System.out.println(pn.toExplainPlanString());

        assertTrue(pn instanceof SendPlanNode);
        pn = pn.getChild(0);

        if (needOrderby) {
            assertTrue(pn instanceof ProjectionPlanNode);
            pn = pn.getChild(0);
            assertTrue(pn instanceof OrderByPlanNode);
            pn = pn.getChild(0);
        }
        assertTrue(pn instanceof IndexScanPlanNode);

        IndexScanPlanNode ispn = (IndexScanPlanNode)pn;
        assertTrue(ispn.getTargetIndexName().contains(indexName));
        assertEquals(lookupType, ispn.getLookupType());
        assertEquals(searchKeys, ispn.getSearchKeyExpressions().size());
        assertEquals(endKeys, ExpressionUtil.uncombine(ispn.getEndExpression()).size());
        assertEquals(predicates, ExpressionUtil.uncombine(ispn.getPredicate()).size());

        assertEquals(0, ExpressionUtil.uncombine(ispn.getInitialExpression()).size());

        assertEquals(sortType, ispn.getSortDirection());
    }

}
TOP

Related Classes of org.voltdb.planner.TestIndexReverseScan

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.