/*
 * 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.ignite.internal.processors.cache.index;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.Comparator;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import org.apache.ignite.cache.query.SqlFieldsQuery;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.testframework.GridTestUtils;
import org.h2.util.DateTimeUtils;
import org.jetbrains.annotations.Nullable;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import static org.apache.ignite.internal.processors.cache.index.BasicSqlTypesIndexTest.IndexType.PK;
import static org.apache.ignite.internal.processors.cache.index.BasicSqlTypesIndexTest.IndexType.SECONDARY_ASC;
import static org.apache.ignite.internal.processors.cache.index.BasicSqlTypesIndexTest.IndexType.SECONDARY_DESC;
import static org.apache.ignite.internal.processors.query.QueryUtils.KEY_FIELD_NAME;
import static org.apache.ignite.internal.processors.query.h2.H2TableDescriptor.PK_IDX_NAME;

/**
 * Basic tests for different types of indexed data
 * for tables created through SQL API.
 */
public class BasicSqlTypesIndexTest extends AbstractIndexingCommonTest {
    /** Count of entries that should be preloaded to the table. */
    private static final int DATSET_SIZE = 1_000;

    /** Table ID counter. */
    private static final AtomicInteger TBL_ID = new AtomicInteger();

    /** Template of CREATE TABLE query with pk and value columns. */
    private static final String CREATE_TBL_PK_ONLY_TEMPLATE =
        "CREATE TABLE \"%s\" (idxVal %s PRIMARY KEY, val INT) WITH \"%s\"";

    /** Template of CREATE TABLE query with pk, value and additional column for indexing. */
    private static final String CREATE_TBL_SECONDARY_INDEX_TEMPLATE =
        "CREATE TABLE \"%s\" (id INT PRIMARY KEY, idxVal %s, val INT) WITH \"%s\"";

    /** Template of CREATE INDEX query for additional column. */
    private static final String CREATE_SECONDARY_INDEX_TEMPLATE = "CREATE INDEX \"%s\" ON \"%s\"(idxVal %s)";

    /** Template of SELECT query with filtering by range and ordering by indexed column. */
    private static final String SELECT_ORDERED_RANGE_TEMPLATE =
        "SELECT val FROM \"%s\" USE INDEX(\"%s\") WHERE %s <= ? ORDER BY %s ASC";

    /** Template of SELECT query with filtering by indexed column. */
    private static final String SELECT_VALUE_TEMPLATE =
        "SELECT val, idxVal FROM \"%s\" USE INDEX(\"%s\") WHERE %s = ?";

    /** Template of INSERT query for two-column table. See {@link #CREATE_TBL_PK_ONLY_TEMPLATE}. */
    private static final String INSERT_PK_ONLY_TEMPLATE = "INSERT INTO \"%s\" (idxVal, val) VALUES (?, ?)";

    /** Template of INSERT query for three-column table. See {@link #CREATE_TBL_SECONDARY_INDEX_TEMPLATE}. */
    private static final String INSERT_SECONDARY_TEMPLATE = "INSERT INTO \"%s\" (id, idxVal, val) VALUES (?, ?, ?)";

    /** Template of UPDATE query for updating value by indexed column. */
    private static final String UPDATE_VAL_TEMPLATE = "UPDATE \"%s\" SET val=? WHERE idxVal=?";

    /** Precision for generator of decimal values. */
    private int decimalPrecision;

    /** Max length for generator of string values. */
    private int maxStrLen;

    /** {@inheritDoc} */
    @Override protected void beforeTestsStarted() throws Exception {
        super.beforeTestsStarted();

        startGridsMultiThreaded(2);
    }

    /** */
    @Before
    public void clearState() {
        decimalPrecision = -1;
        maxStrLen = 40;
    }

    /** */
    @Test
    public void testSqlBooleanTypeIndex() {
        String idxTypeStr = "BOOLEAN";
        Class<Boolean> idxCls = Boolean.class;

        createPopulateAndVerify(idxTypeStr, idxCls, Boolean::compareTo, PK, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, Boolean::compareTo, PK, "BACKUPS=1,AFFINITY_KEY=idxVal");
        createPopulateAndVerify(idxTypeStr, idxCls, Boolean::compareTo, SECONDARY_DESC, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, Boolean::compareTo, SECONDARY_ASC, "BACKUPS=1");
    }

    /** */
    @Test
    public void testSqlBigintTypeIndex() {
        String idxTypeStr = "BIGINT";
        Class<Long> idxCls = Long.class;

        createPopulateAndVerify(idxTypeStr, idxCls, Long::compareTo, PK, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, Long::compareTo, PK, "BACKUPS=1,AFFINITY_KEY=idxVal");
        createPopulateAndVerify(idxTypeStr, idxCls, Long::compareTo, SECONDARY_DESC, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, Long::compareTo, SECONDARY_ASC, "BACKUPS=1");
    }

    /** */
    @Test
    public void testSqlDecimalTypeIndex() {
        String idxTypeStr = "DECIMAL";
        Class<BigDecimal> idxCls = BigDecimal.class;

        createPopulateAndVerify(idxTypeStr, idxCls, BigDecimal::compareTo, PK, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, BigDecimal::compareTo, PK, "BACKUPS=1,AFFINITY_KEY=idxVal");
        createPopulateAndVerify(idxTypeStr, idxCls, BigDecimal::compareTo, SECONDARY_DESC, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, BigDecimal::compareTo, SECONDARY_ASC, "BACKUPS=1");
    }

    /** */
    @Test
    public void testSqlDecimalFixedPrecisionTypeIndex() {
        decimalPrecision = 3;

        String idxTypeStr = "DECIMAL(20,3)";
        Class<BigDecimal> idxCls = BigDecimal.class;

        createPopulateAndVerify(idxTypeStr, idxCls, BigDecimal::compareTo, PK, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, BigDecimal::compareTo, PK, "BACKUPS=1,AFFINITY_KEY=idxVal");
        createPopulateAndVerify(idxTypeStr, idxCls, BigDecimal::compareTo, SECONDARY_DESC, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, BigDecimal::compareTo, SECONDARY_ASC, "BACKUPS=1");
    }

    /** */
    @Test
    public void testSqlNumericTypeIndex() {
        decimalPrecision = 0;

        String idxTypeStr = "NUMERIC(10)";
        Class<BigDecimal> idxCls = BigDecimal.class;

        createPopulateAndVerify(idxTypeStr, idxCls, BigDecimal::compareTo, PK, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, BigDecimal::compareTo, PK, "BACKUPS=1,AFFINITY_KEY=idxVal");
        createPopulateAndVerify(idxTypeStr, idxCls, BigDecimal::compareTo, SECONDARY_DESC, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, BigDecimal::compareTo, SECONDARY_ASC, "BACKUPS=1");
    }

    /** */
    @Test
    public void testSqlDoubleTypeIndex() {
        String idxTypeStr = "DOUBLE";
        Class<Double> idxCls = Double.class;

        createPopulateAndVerify(idxTypeStr, idxCls, Double::compareTo, PK, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, Double::compareTo, PK, "BACKUPS=1,AFFINITY_KEY=idxVal");
        createPopulateAndVerify(idxTypeStr, idxCls, Double::compareTo, SECONDARY_DESC, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, Double::compareTo, SECONDARY_ASC, "BACKUPS=1");
    }

    /** */
    @Test
    public void testSqlIntTypeIndex() {
        String idxTypeStr = "INT";
        Class<Integer> idxCls = Integer.class;

        createPopulateAndVerify(idxTypeStr, idxCls, Integer::compareTo, PK, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, Integer::compareTo, PK, "BACKUPS=1,AFFINITY_KEY=idxVal");
        createPopulateAndVerify(idxTypeStr, idxCls, Integer::compareTo, SECONDARY_DESC, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, Integer::compareTo, SECONDARY_ASC, "BACKUPS=1");
    }

    /** */
    @Test
    public void testSqlRealTypeIndex() {
        String idxTypeStr = "REAL";
        Class<Float> idxCls = Float.class;

        createPopulateAndVerify(idxTypeStr, idxCls, Float::compareTo, PK, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, Float::compareTo, PK, "BACKUPS=1,AFFINITY_KEY=idxVal");
        createPopulateAndVerify(idxTypeStr, idxCls, Float::compareTo, SECONDARY_DESC, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, Float::compareTo, SECONDARY_ASC, "BACKUPS=1");
    }

    /** */
    @Test
    public void testSqlTinyintTypeIndex() {
        String idxTypeStr = "TINYINT";
        Class<Byte> idxCls = Byte.class;

        createPopulateAndVerify(idxTypeStr, idxCls, Byte::compareTo, PK, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, Byte::compareTo, PK, "BACKUPS=1,AFFINITY_KEY=idxVal");
        createPopulateAndVerify(idxTypeStr, idxCls, Byte::compareTo, SECONDARY_DESC, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, Byte::compareTo, SECONDARY_ASC, "BACKUPS=1");
    }

    /** */
    @Test
    public void testSqlSmallintTypeIndex() {
        String idxTypeStr = "SMALLINT";
        Class<Short> idxCls = Short.class;

        createPopulateAndVerify(idxTypeStr, idxCls, Short::compareTo, PK, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, Short::compareTo, PK, "BACKUPS=1,AFFINITY_KEY=idxVal");
        createPopulateAndVerify(idxTypeStr, idxCls, Short::compareTo, SECONDARY_DESC, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, Short::compareTo, SECONDARY_ASC, "BACKUPS=1");
    }

    /** */
    @Test
    public void testSqlVarcharTypeIndex() {
        String idxTypeStr = "VARCHAR";
        Class<String> idxCls = String.class;

        createPopulateAndVerify(idxTypeStr, idxCls, String::compareTo, PK, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, String::compareTo, PK, "BACKUPS=1,AFFINITY_KEY=idxVal");
        createPopulateAndVerify(idxTypeStr, idxCls, String::compareTo, SECONDARY_DESC, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, String::compareTo, SECONDARY_ASC, "BACKUPS=1");
    }

    /** */
    @Test
    public void testSqlCharTypeIndex() {
        maxStrLen = 10;

        String idxTypeStr = "CHAR(10)";
        Class<String> idxCls = String.class;

        createPopulateAndVerify(idxTypeStr, idxCls, String::compareTo, PK, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, String::compareTo, PK, "BACKUPS=1,AFFINITY_KEY=idxVal");
        createPopulateAndVerify(idxTypeStr, idxCls, String::compareTo, SECONDARY_DESC, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, String::compareTo, SECONDARY_ASC, "BACKUPS=1");
    }

    /** */
    @Test
    public void testSqlDateTypeIndex() {
        String idxTypeStr = "DATE";
        Class<Date> idxCls = Date.class;

        // TODO: https://issues.apache.org/jira/browse/IGNITE-8552
//        createPopulateAndVerify(idxTypeStr, idxCls, Date::compareTo, PK, "BACKUPS=1");
//        createPopulateAndVerify(idxTypeStr, idxCls, Date::compareTo, PK, "BACKUPS=1,AFFINITY_KEY=idxVal");
        createPopulateAndVerify(idxTypeStr, idxCls, Date::compareTo, SECONDARY_DESC, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, Date::compareTo, SECONDARY_ASC, "BACKUPS=1");
    }

    /** */
    @Test
    public void testSqlTimeTypeIndex() {
        String idxTypeStr = "TIME";
        Class<Time> idxCls = Time.class;

        Comparator<Time> comp = new Comparator<Time>() {
            @Override public int compare(Time o1, Time o2) {
                GregorianCalendar cal = new GregorianCalendar();

                long l1 = DateTimeUtils.convertTime(o1, cal).getNanos();
                long l2 = DateTimeUtils.convertTime(o2, cal).getNanos();

                return Long.compare(l1, l2);
            }
        };

        createPopulateAndVerify(idxTypeStr, idxCls, comp, PK, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, comp, PK, "BACKUPS=1,AFFINITY_KEY=idxVal");
        createPopulateAndVerify(idxTypeStr, idxCls, comp, SECONDARY_DESC, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, comp, SECONDARY_ASC, "BACKUPS=1");
    }

    /** */
    @Test
    public void testSqlTimestampTypeIndex() {
        String idxTypeStr = "TIMESTAMP";
        Class<Timestamp> idxCls = Timestamp.class;

        createPopulateAndVerify(idxTypeStr, idxCls, Timestamp::compareTo, PK, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, Timestamp::compareTo, PK, "BACKUPS=1,AFFINITY_KEY=idxVal");
        createPopulateAndVerify(idxTypeStr, idxCls, Timestamp::compareTo, SECONDARY_DESC, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, Timestamp::compareTo, SECONDARY_ASC, "BACKUPS=1");
    }

    /** */
    @Test
    public void testSqlBynaryTypeIndex() {
        String idxTypeStr = "BINARY";
        Class<byte[]> idxCls = byte[].class;

        createPopulateAndVerify(idxTypeStr, idxCls, F::compareArrays, PK, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, F::compareArrays, PK, "BACKUPS=1,AFFINITY_KEY=idxVal");
        createPopulateAndVerify(idxTypeStr, idxCls, F::compareArrays, SECONDARY_DESC, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, F::compareArrays, SECONDARY_ASC, "BACKUPS=1");
    }

    /** */
    @Test
    public void testSqlUuidTypeIndex() {
        String idxTypeStr = "UUID";
        Class<UUID> idxCls = UUID.class;

        createPopulateAndVerify(idxTypeStr, idxCls, UUID::compareTo, PK, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, UUID::compareTo, PK, "BACKUPS=1,AFFINITY_KEY=idxVal");
        createPopulateAndVerify(idxTypeStr, idxCls, UUID::compareTo, SECONDARY_DESC, "BACKUPS=1");
        createPopulateAndVerify(idxTypeStr, idxCls, UUID::compareTo, SECONDARY_ASC, "BACKUPS=1");
    }

    /**
     * Executes test scenario: <ul>
     *     <li>Create table</li>
     *     <li>Create necessary indexes</li>
     *     <li>Populate table with random data</li>
     *     <li>Verify range query on created table</li>
     *     <li>Verify that table stores the same data as the generated dataset</li>
     *     <li>Drop table</li>
     * </ul>
     *
     *
     * @param idxTypeStr Index type in string (e.g. 'INT').
     * @param idxTypeCls Index type class.
     * @param idxType Whether index should be primary key or not.
     * @param benefits Benefits will be used for table creation
     * (i.e. {@code CREATE TABLE friends() WITH "<benefits>"}).
     * @param <T> Java type mapping of the indexed column.
     */
    private <T> void createPopulateAndVerify(String idxTypeStr, Class<T> idxTypeCls, Comparator<T> comp,
        IndexType idxType, @Nullable String benefits) {
        String tblName = idxTypeStr + "_TBL" + TBL_ID.incrementAndGet();

        try {
            String createTblSql = String.format(
                idxType == PK ? CREATE_TBL_PK_ONLY_TEMPLATE : CREATE_TBL_SECONDARY_INDEX_TEMPLATE,
                tblName, idxTypeStr, benefits != null ? benefits : ""
            );

            execSql(createTblSql);

            String idxName;
            String idxFieldName;

            if (idxType != PK) {
                idxName = "idxVal_idx";
                idxFieldName = "idxVal";

                execSql(String.format(CREATE_SECONDARY_INDEX_TEMPLATE, idxName, tblName,
                    idxType == SECONDARY_ASC ? "ASC" : "DESC"));
            }
            else {
                idxName = PK_IDX_NAME;
                idxFieldName = KEY_FIELD_NAME;
            }

            Map<T, Integer> data = new TreeMap<>(comp);

            populateTable(data, tblName, idxTypeCls, idxType == PK);

            verifyRange(data, tblName, idxFieldName, idxName, comp);
            verifyEach(data, tblName, idxFieldName, idxName);
        }
        finally {
            execSql("DROP TABLE IF EXISTS \"" + tblName + "\"");
        }
    }

    /**
     * Populate table with random data.
     *
     * @param data Map which will be used to store all generated data.
     * @param tblName Table name that should be populated.
     * @param idxValCls Class of indexed value. Used for generating random value
     * of the required type.
     * @param pk Whether indexed value is primary key or not.
     * @param <T> Java type mapping of the indexed column.
     */
    private <T> void populateTable(Map<T, Integer> data, String tblName, Class<T> idxValCls, boolean pk) {
        for (int i = 0; i < DATSET_SIZE; i++) {
            int id = nextVal(Integer.class);
            T idxVal = nextVal(idxValCls);
            int val = nextVal(Integer.class);

            if (data.put(idxVal, val) == null) {
                if (pk)
                    execSql(String.format(INSERT_PK_ONLY_TEMPLATE, tblName), idxVal, val);
                else
                    execSql(String.format(INSERT_SECONDARY_TEMPLATE, tblName), id, idxVal, val);
            }
            else
                execSql(String.format(UPDATE_VAL_TEMPLATE, tblName), val, idxVal);
        }
    }

    /**
     * Generates random value for the given class.
     *
     * @param cls Class of the required value.
     * @param <T> Java type mapping of the indexed column.
     *
     * @return Generated value.
     */
    private <T> T nextVal(Class<T> cls) {
        if (cls.isAssignableFrom(Boolean.class))
            return cls.cast(ThreadLocalRandom.current().nextBoolean());

        if (cls.isAssignableFrom(Byte.class))
            return cls.cast((byte)ThreadLocalRandom.current().nextInt());

        if (cls.isAssignableFrom(Short.class))
            return cls.cast((short)ThreadLocalRandom.current().nextInt());

        if (cls.isAssignableFrom(Integer.class))
            return cls.cast(ThreadLocalRandom.current().nextInt());

        if (cls.isAssignableFrom(Long.class))
            return cls.cast(ThreadLocalRandom.current().nextLong());

        if (cls.isAssignableFrom(Float.class))
            return cls.cast(ThreadLocalRandom.current().nextFloat());

        if (cls.isAssignableFrom(Double.class))
            return cls.cast(ThreadLocalRandom.current().nextDouble());

        if (cls.isAssignableFrom(BigDecimal.class)) {
            BigDecimal bd = new BigDecimal(ThreadLocalRandom.current().nextDouble());

            if (decimalPrecision >= 0)
                bd = bd.setScale(decimalPrecision, RoundingMode.HALF_UP);

            return cls.cast(bd);
        }

        if (cls.isAssignableFrom(String.class))
            return cls.cast(GridTestUtils.randomString(ThreadLocalRandom.current(), 1, maxStrLen));

        if (cls.isAssignableFrom(Date.class))
            return cls.cast(new Date(ThreadLocalRandom.current().nextLong()));

        if (cls.isAssignableFrom(Time.class))
            return cls.cast(new Time(ThreadLocalRandom.current().nextLong()));

        if (cls.isAssignableFrom(Timestamp.class))
            return cls.cast(new Timestamp(ThreadLocalRandom.current().nextLong()));

        if (cls.isAssignableFrom(UUID.class))
            return cls.cast(new UUID(
                ThreadLocalRandom.current().nextLong(),
                ThreadLocalRandom.current().nextLong()
            ));

        if (cls.isAssignableFrom(byte[].class))
            return cls.cast(GridTestUtils.randomString(ThreadLocalRandom.current(), 1, maxStrLen).getBytes());

        throw new IllegalStateException("There is no generator for class=" + cls.getSimpleName());
    }

    /**
     * Verifies range querying.
     *
     * @param data Testing dataset.
     * @param tblName Name of the table from which values should be queried.
     * @param idxFieldName Name of the indexed field.
     * @param idxName Name of the index.
     * @param comp Comparator.
     * @param <T> Java type mapping of the indexed column.
     */
    private <T> void verifyRange(Map<T, Integer> data, String tblName,
        String idxFieldName, String idxName, Comparator<T> comp) {
        T val = getRandom(data.keySet());

        List<List<?>> res = execSql(String.format(SELECT_ORDERED_RANGE_TEMPLATE, tblName, idxName, idxFieldName, idxFieldName), val);

        List<Integer> exp = data.entrySet().stream()
            .filter(e -> comp.compare(e.getKey(), val) <= 0)
            .sorted((e1, e2) -> comp.compare(e1.getKey(), e2.getKey()))
            .map(Map.Entry::getValue)
            .collect(Collectors.toList());

        List<Integer> act = res.stream()
            .flatMap(List::stream)
            .map(e -> (Integer)e)
            .collect(Collectors.toList());

        Assert.assertEquals(exp, act);
    }

    /**
     * Verifies that table content equals to generated dataset.
     *
     * @param data Testing dataset.
     * @param tblName Name of the table from which values should be queried.
     * @param idxFieldName Name of the indexed field.
     * @param idxName Name of the index.
     * @param <T> Java type mapping of the indexed column.
     */
    private <T> void verifyEach(Map<T, Integer> data, String tblName, String idxFieldName, String idxName) {
        for (Map.Entry<T, Integer> entry : data.entrySet()) {
            List<List<?>> res = execSql(
                String.format(SELECT_VALUE_TEMPLATE, tblName, idxName, idxFieldName), entry.getKey()
            );

            Assert.assertFalse("Result should not be empty", res.isEmpty());
            Assert.assertFalse("Result should contain at least one column", res.get(0).isEmpty());
            Assert.assertEquals(entry.getValue(), res.get(0).get(0));
        }
    }

    /**
     * Returns random element from collection.
     *
     * @param col Collection from which random element should be returned.
     * @param <T> Java type mapping of the indexed column.
     *
     * @return Random element from given collection.
     */
    private <T> T getRandom(Collection<T> col) {
        int rndIdx = ThreadLocalRandom.current().nextInt(col.size());

        int i = 0;

        for (T el : col) {
            if (i++ == rndIdx)
                return el;
        }

        return null;
    }

    /**
     * @param qry Query.
     * @param args Args.
     */
    private List<List<?>> execSql(String qry, Object... args) {
        return grid(0).context().query().querySqlFields(new SqlFieldsQuery(qry).setArgs(args), false).getAll();
    }

    /** Type of the index to create. */
    enum IndexType {
        /** Primary key. */
        PK,

        /** Secondary index with ascending sorting. */
        SECONDARY_ASC,

        /** Secondary index with descending sorting. */
        SECONDARY_DESC
    }
}
