This is an automated email from the ASF dual-hosted git repository. amashenkov pushed a commit to branch ignite-20337 in repository https://gitbox.apache.org/repos/asf/ignite-3.git
commit a16d9a3f5907e15bd9d53c1507eb78477c3dae09 Author: amashenkov <andrey.mashen...@gmail.com> AuthorDate: Sat Sep 2 12:46:36 2023 +0300 Minor refactoring. --- .../ignite/internal/sql/engine/ItMetadataTest.java | 15 ++-- .../internal/sql/engine/util/ColumnMatcher.java | 29 +++++++ .../internal/sql/engine/util/MetadataMatcher.java | 5 +- .../internal/sql/engine/util/QueryChecker.java | 97 ++++++++++++---------- 4 files changed, 94 insertions(+), 52 deletions(-) diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItMetadataTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItMetadataTest.java index ef6bfcf166..c036dfa244 100644 --- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItMetadataTest.java +++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItMetadataTest.java @@ -21,8 +21,6 @@ import static java.util.stream.Collectors.joining; import static java.util.stream.Stream.generate; import static org.apache.ignite.sql.ColumnMetadata.UNDEFINED_SCALE; -import java.time.Duration; -import java.time.Period; import org.apache.ignite.internal.sql.engine.util.MetadataMatcher; import org.apache.ignite.sql.ColumnType; import org.junit.jupiter.api.BeforeAll; @@ -92,9 +90,14 @@ public class ItMetadataTest extends ClusterPerClassIntegrationTest { public void infixTypeCast() { assertQuery("select id, id::tinyint as tid, id::smallint as sid, id::varchar as vid, id::interval hour, " + "id::interval year from person") - .columnNames("ID", "TID", "SID", "VID", "ID :: INTERVAL INTERVAL_HOUR", "ID :: INTERVAL INTERVAL_YEAR") - .columnTypes(Integer.class, Byte.class, Short.class, String.class, Duration.class, Period.class) - .check(); + .columnMetadata( + new MetadataMatcher().name("ID").type(ColumnType.INT32), + new MetadataMatcher().name("TID").type(ColumnType.INT8), + new MetadataMatcher().name("SID").type(ColumnType.INT16), + new MetadataMatcher().name("VID").type(ColumnType.STRING), + new MetadataMatcher().name("ID :: INTERVAL INTERVAL_HOUR").type(ColumnType.DURATION), + new MetadataMatcher().name("ID :: INTERVAL INTERVAL_YEAR").type(ColumnType.PERIOD) + ).check(); } @Test @@ -109,7 +112,7 @@ public class ItMetadataTest extends ClusterPerClassIntegrationTest { @Test public void metadata() { sql("CREATE TABLE METADATA_TABLE (" + "ID INT PRIMARY KEY, " - + "BOOLEAN_C BOOLEAN, " + + "BOOLEAN_C BOOLEAN, " // Exact numeric types + "TINY_C TINYINT, " // TINYINT is not a part of any SQL standard. diff --git a/modules/sql-engine/src/testFixtures/java/org/apache/ignite/internal/sql/engine/util/ColumnMatcher.java b/modules/sql-engine/src/testFixtures/java/org/apache/ignite/internal/sql/engine/util/ColumnMatcher.java new file mode 100644 index 0000000000..02eb537870 --- /dev/null +++ b/modules/sql-engine/src/testFixtures/java/org/apache/ignite/internal/sql/engine/util/ColumnMatcher.java @@ -0,0 +1,29 @@ +/* + * 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.engine.util; + +import org.apache.ignite.sql.ColumnMetadata; + +/** + * Column metadata matcher interface. + */ +@FunctionalInterface +public interface ColumnMatcher { + /** Validates column metadata. */ + void check(ColumnMetadata columnMetadata); +} diff --git a/modules/sql-engine/src/testFixtures/java/org/apache/ignite/internal/sql/engine/util/MetadataMatcher.java b/modules/sql-engine/src/testFixtures/java/org/apache/ignite/internal/sql/engine/util/MetadataMatcher.java index f65d2d0fea..bc78b1ff0f 100644 --- a/modules/sql-engine/src/testFixtures/java/org/apache/ignite/internal/sql/engine/util/MetadataMatcher.java +++ b/modules/sql-engine/src/testFixtures/java/org/apache/ignite/internal/sql/engine/util/MetadataMatcher.java @@ -34,7 +34,7 @@ import org.junit.jupiter.api.function.Executable; /** * Column metadata checker. */ -public class MetadataMatcher { +public class MetadataMatcher implements ColumnMatcher { /** Marker object. */ private static final Object NO_CHECK = new Object() { @Override @@ -132,7 +132,8 @@ public class MetadataMatcher { * * @param actualMeta Metadata to check. */ - void check(ColumnMetadata actualMeta) { + @Override + public void check(ColumnMetadata actualMeta) { List<Executable> matchers = new ArrayList<>(); if (name != NO_CHECK) { diff --git a/modules/sql-engine/src/testFixtures/java/org/apache/ignite/internal/sql/engine/util/QueryChecker.java b/modules/sql-engine/src/testFixtures/java/org/apache/ignite/internal/sql/engine/util/QueryChecker.java index a676e3cdc2..6b925b8e25 100644 --- a/modules/sql-engine/src/testFixtures/java/org/apache/ignite/internal/sql/engine/util/QueryChecker.java +++ b/modules/sql-engine/src/testFixtures/java/org/apache/ignite/internal/sql/engine/util/QueryChecker.java @@ -273,6 +273,34 @@ public abstract class QueryChecker { String createQuery(); } + /** Validates method {@link #check()} method was called on {@link QueryChecker}. */ + private static class QueryCheckerValidator { + QueryChecker currentChecker; + Throwable stacktrace; + + void set(QueryChecker newChecker) { + if (currentChecker != null) { + throw new IllegalStateException("Found previous QueryChecker.", stacktrace); + } + + currentChecker = newChecker; + stacktrace = new AssertionError("Method `check()` wasn't called."); + } + + void remove(QueryChecker queryChecker) { + if (queryChecker == currentChecker) { + currentChecker = null; + } + + IllegalStateException ex = new IllegalStateException("Unexpected QueryChecker."); + ex.addSuppressed(stacktrace); + + throw ex; + } + } + + private static final QueryCheckerValidator CURRENT_CHECKER_HOLDER = new QueryCheckerValidator(); + private final QueryTemplate queryTemplate; private final ArrayList<Matcher<String>> planMatchers = new ArrayList<>(); @@ -281,18 +309,12 @@ public abstract class QueryChecker { private List<List<?>> expectedResult; - private List<String> expectedColumnNames; - - private List<Type> expectedColumnTypes; - - private List<MetadataMatcher> metadataMatchers; + private List<ColumnMatcher> metadataMatchers; private boolean ordered; private Object[] params = OBJECT_EMPTY_ARRAY; - private String exactPlan; - private Transaction tx; /** @@ -314,6 +336,9 @@ public abstract class QueryChecker { public QueryChecker(Transaction tx, QueryTemplate queryTemplate) { this.tx = tx; this.queryTemplate = new AddDisabledRulesTemplate(queryTemplate, disabledRules); + + //noinspection ThisEscapedInObjectConstruction + CURRENT_CHECKER_HOLDER.set(this); } /** @@ -419,7 +444,11 @@ public abstract class QueryChecker { * @return This. */ public QueryChecker columnNames(String... columns) { - expectedColumnNames = Arrays.asList(columns); + assert metadataMatchers == null; + + metadataMatchers = Arrays.stream(columns) + .map(name -> new MetadataMatcher().name(name)) + .collect(Collectors.toList()); return this; } @@ -430,7 +459,15 @@ public abstract class QueryChecker { * @return This. */ public QueryChecker columnTypes(Type... columns) { - expectedColumnTypes = Arrays.asList(columns); + assert metadataMatchers == null; + + metadataMatchers = Arrays.stream(columns) + .map(t -> (ColumnMatcher) columnMetadata -> { + Class<?> type = ColumnType.columnTypeToClass(columnMetadata.type()); + + assertThat("Column type don't match", type, equalTo(t)); + }) + .collect(Collectors.toList()); return this; } @@ -441,18 +478,9 @@ public abstract class QueryChecker { * @return This. */ public QueryChecker columnMetadata(MetadataMatcher... matchers) { - metadataMatchers = Arrays.asList(matchers); + assert metadataMatchers == null; - return this; - } - - /** - * Sets plan. - * - * @return This. - */ - public QueryChecker planEquals(String plan) { - exactPlan = plan; + metadataMatchers = Arrays.asList(matchers); return this; } @@ -461,6 +489,8 @@ public abstract class QueryChecker { * Run checks. */ public void check() { + CURRENT_CHECKER_HOLDER.remove(this); + // Check plan. QueryProcessor qryProc = getEngine(); @@ -472,7 +502,7 @@ public abstract class QueryChecker { try { - if (!CollectionUtils.nullOrEmpty(planMatchers) || exactPlan != null) { + if (!CollectionUtils.nullOrEmpty(planMatchers)) { CompletableFuture<AsyncSqlCursor<List<Object>>> explainCursors = qryProc.querySingleAsync(sessionId, context, transactions(), "EXPLAIN PLAN FOR " + qry, params); @@ -486,10 +516,6 @@ public abstract class QueryChecker { assertThat("Invalid plan:\n" + actualPlan, actualPlan, matcher); } } - - if (exactPlan != null) { - assertEquals(exactPlan, actualPlan); - } } // Check result. CompletableFuture<AsyncSqlCursor<List<Object>>> cursors = @@ -499,31 +525,14 @@ public abstract class QueryChecker { checkMetadata(cur); - if (expectedColumnNames != null) { - List<String> colNames = cur.metadata().columns().stream() - .map(ColumnMetadata::name) - .collect(Collectors.toList()); - - assertThat("Column names don't match", colNames, equalTo(expectedColumnNames)); - } - - if (expectedColumnTypes != null) { - List<Type> colTypes = cur.metadata().columns().stream() - .map(ColumnMetadata::type) - .map(ColumnType::columnTypeToClass) - .collect(Collectors.toList()); - - assertThat("Column types don't match", colTypes, equalTo(expectedColumnTypes)); - } - if (metadataMatchers != null) { List<ColumnMetadata> columnMetadata = cur.metadata().columns(); Iterator<ColumnMetadata> valueIterator = columnMetadata.iterator(); - Iterator<MetadataMatcher> matcherIterator = metadataMatchers.iterator(); + Iterator<ColumnMatcher> matcherIterator = metadataMatchers.iterator(); while (matcherIterator.hasNext() && valueIterator.hasNext()) { - MetadataMatcher matcher = matcherIterator.next(); + ColumnMatcher matcher = matcherIterator.next(); ColumnMetadata actualElement = valueIterator.next(); matcher.check(actualElement);