blob: f70a565cd37f3150e0eba7489d900868b466dd70 [file] [log] [blame]
/*
* 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.sql;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import java.util.List;
import org.apache.ignite.internal.ClusterPerClassIntegrationTest;
import org.apache.ignite.internal.app.IgniteImpl;
import org.apache.ignite.internal.sql.engine.SqlQueryProcessor;
import org.apache.ignite.internal.sql.engine.util.InjectQueryCheckerFactory;
import org.apache.ignite.internal.sql.engine.util.QueryChecker;
import org.apache.ignite.internal.sql.engine.util.QueryCheckerExtension;
import org.apache.ignite.internal.sql.engine.util.QueryCheckerFactory;
import org.apache.ignite.internal.systemview.SystemViewManagerImpl;
import org.apache.ignite.internal.tx.InternalTransaction;
import org.apache.ignite.internal.tx.TxManager;
import org.apache.ignite.sql.ColumnMetadata;
import org.apache.ignite.sql.IgniteSql;
import org.apache.ignite.table.Table;
import org.apache.ignite.tx.IgniteTransactions;
import org.jetbrains.annotations.Nullable;
import org.junit.jupiter.api.extension.ExtendWith;
/**
* Base class for SQL integration tests.
*/
@ExtendWith(QueryCheckerExtension.class)
public class BaseSqlIntegrationTest extends ClusterPerClassIntegrationTest {
@InjectQueryCheckerFactory
protected static QueryCheckerFactory queryCheckerFactory;
/**
* Executes the query and validates any asserts passed to the builder.
*
* @param qry Query to execute.
* @return Instance of QueryChecker.
*/
protected static QueryChecker assertQuery(String qry) {
return assertQuery((InternalTransaction) null, qry);
}
protected static QueryChecker assertQuery(IgniteImpl node, String qry) {
return assertQuery(node, null, qry);
}
/**
* Executes the query with the given transaction and validates any asserts passed to the builder.
*
* @param tx Transaction.
* @param qry Query to execute.
* @return Instance of QueryChecker.
*/
protected static QueryChecker assertQuery(@Nullable InternalTransaction tx, String qry) {
return assertQuery(CLUSTER.aliveNode(), tx, qry);
}
protected static QueryChecker assertQuery(IgniteImpl node, @Nullable InternalTransaction tx, String qry) {
return queryCheckerFactory.create(node.name(), node.queryEngine(), node.transactions(), tx, qry);
}
/**
* Used for join checks, disables other join rules for executing exact join algo.
*
* @param qry Query for check.
* @param joinType Type of join algo.
* @param rules Additional rules need to be disabled.
*/
protected static QueryChecker assertQuery(String qry, JoinType joinType, String... rules) {
return assertQuery(qry)
.disableRules(joinType.disabledRules)
.disableRules(rules);
}
/**
* Used for query with aggregates checks, disables other aggregate rules for executing exact agregate algo.
*
* @param qry Query for check.
* @param aggregateType Type of aggregate algo.
* @param rules Additional rules need to be disabled.
*/
protected static QueryChecker assertQuery(String qry, AggregateType aggregateType, String... rules) {
return assertQuery(qry)
.disableRules(aggregateType.disabledRules)
.disableRules(rules);
}
/**
* Join type.
*/
protected enum JoinType {
NESTED_LOOP(
"CorrelatedNestedLoopJoin",
"JoinCommuteRule",
"MergeJoinConverter",
"HashJoinConverter"
),
MERGE(
"CorrelatedNestedLoopJoin",
"JoinCommuteRule",
"NestedLoopJoinConverter",
"HashJoinConverter"
),
CORRELATED(
"MergeJoinConverter",
"JoinCommuteRule",
"NestedLoopJoinConverter",
"HashJoinConverter"
),
HASHJOIN(
"MergeJoinConverter",
"JoinCommuteRule",
"NestedLoopJoinConverter",
"CorrelatedNestedLoopJoin"
);
private final String[] disabledRules;
JoinType(String... disabledRules) {
this.disabledRules = disabledRules;
}
}
/**
* Aggregate type.
*/
protected enum AggregateType {
SORT(
"ColocatedHashAggregateConverterRule",
"ColocatedSortAggregateConverterRule",
"MapReduceHashAggregateConverterRule"
),
HASH(
"ColocatedHashAggregateConverterRule",
"ColocatedSortAggregateConverterRule",
"MapReduceSortAggregateConverterRule"
);
private final String[] disabledRules;
AggregateType(String... disabledRules) {
this.disabledRules = disabledRules;
}
}
protected static void createAndPopulateTable() {
createTable(DEFAULT_TABLE_NAME, 1, 8);
int idx = 0;
insertData("person", List.of("ID", "NAME", "SALARY"), new Object[][]{
{idx++, "Igor", 10d},
{idx++, null, 15d},
{idx++, "Ilya", 15d},
{idx++, "Roma", 10d},
{idx, "Roma", 10d}
});
}
protected static void checkMetadata(ColumnMetadata expectedMeta, ColumnMetadata actualMeta) {
assertAll("Missmatch:\n expected = " + expectedMeta + ",\n actual = " + actualMeta,
() -> assertEquals(expectedMeta.name(), actualMeta.name(), "name"),
() -> assertEquals(expectedMeta.nullable(), actualMeta.nullable(), "nullable"),
() -> assertSame(expectedMeta.type(), actualMeta.type(), "type"),
() -> assertEquals(expectedMeta.precision(), actualMeta.precision(), "precision"),
() -> assertEquals(expectedMeta.scale(), actualMeta.scale(), "scale"),
() -> assertSame(expectedMeta.valueClass(), actualMeta.valueClass(), "value class"),
() -> {
if (expectedMeta.origin() == null) {
assertNull(actualMeta.origin(), "origin");
return;
}
assertNotNull(actualMeta.origin(), "origin");
assertEquals(expectedMeta.origin().schemaName(), actualMeta.origin().schemaName(), " origin schema");
assertEquals(expectedMeta.origin().tableName(), actualMeta.origin().tableName(), " origin table");
assertEquals(expectedMeta.origin().columnName(), actualMeta.origin().columnName(), " origin column");
}
);
}
/**
* Returns transaction manager for first cluster node.
*/
protected IgniteTransactions igniteTx() {
return CLUSTER.aliveNode().transactions();
}
/**
* Gets the SQL API.
*
* @return SQL API.
*/
protected IgniteSql igniteSql() {
return CLUSTER.aliveNode().sql();
}
/**
* Returns internal {@code SqlQueryProcessor} for first cluster node.
*/
protected SqlQueryProcessor queryProcessor() {
return (SqlQueryProcessor) CLUSTER.aliveNode().queryEngine();
}
/**
* Returns internal {@code TxManager} for first cluster node.
*/
protected TxManager txManager() {
return CLUSTER.aliveNode().txManager();
}
protected static Table table(String canonicalName) {
return CLUSTER.aliveNode().tables().table(canonicalName);
}
/**
* Returns internal {@code SystemViewManager} for first cluster node.
*/
protected SystemViewManagerImpl systemViewManager() {
return (SystemViewManagerImpl) CLUSTER.aliveNode().systemViewManager();
}
}