From 86ef7ae452dc1fa28f7cbe6ddee1226508076173 Mon Sep 17 00:00:00 2001 From: Youssef Hatem Date: Wed, 5 Feb 2025 19:48:55 +0000 Subject: [PATCH 1/3] set skip and limit for the recursive union cursor correctly. --- .../plans/RecordQueryRecursiveUnionPlan.java | 8 ++-- .../relational/yamltests/Matchers.java | 24 +++++++---- yaml-tests/src/test/resources/cte.yamsql | 8 ++++ .../src/test/resources/recursive-cte.yamsql | 43 +++++++++++++++++++ 4 files changed, 71 insertions(+), 12 deletions(-) diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/plans/RecordQueryRecursiveUnionPlan.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/plans/RecordQueryRecursiveUnionPlan.java index 7571f962be..e00cd1510e 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/plans/RecordQueryRecursiveUnionPlan.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/plans/RecordQueryRecursiveUnionPlan.java @@ -150,16 +150,18 @@ public RecordCursor executePlan(@Nonnull final @Nullable final byte[] continuation, @Nonnull final ExecuteProperties executeProperties) { final var type = getInnerTypeDescriptor(context); + final var childExecuteProperties = executeProperties.clearSkipAndLimit(); final var recursiveStateManager = new RecursiveStateManagerImpl( (initialContinuation, evaluationContext) -> getInitialStatePlan().executePlan(store, evaluationContext, - initialContinuation == null ? null : initialContinuation.toByteArray(), executeProperties), + initialContinuation == null ? null : initialContinuation.toByteArray(), childExecuteProperties), (recursiveContinuation, evaluationContext) -> getRecursiveStatePlan().executePlan(store, evaluationContext, - recursiveContinuation == null ? null : recursiveContinuation.toByteArray(), executeProperties), + recursiveContinuation == null ? null : recursiveContinuation.toByteArray(), childExecuteProperties), context, tempTableScanAlias, tempTableInsertAlias, proto -> TempTable.from(proto, type), store.getContext().getTempTableFactory(), continuation); - return new RecursiveUnionCursor<>(recursiveStateManager, store.getExecutor()); + return new RecursiveUnionCursor<>(recursiveStateManager, store.getExecutor()) + .skipThenLimit(executeProperties.getSkip(), executeProperties.getReturnedRowLimit()); } @Nullable diff --git a/yaml-tests/src/main/java/com/apple/foundationdb/relational/yamltests/Matchers.java b/yaml-tests/src/main/java/com/apple/foundationdb/relational/yamltests/Matchers.java index 411d507809..ef09a49f98 100644 --- a/yaml-tests/src/main/java/com/apple/foundationdb/relational/yamltests/Matchers.java +++ b/yaml-tests/src/main/java/com/apple/foundationdb/relational/yamltests/Matchers.java @@ -30,6 +30,7 @@ import com.apple.foundationdb.relational.util.SpotBugsSuppressWarnings; import com.google.common.collect.HashMultiset; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Multiset; import com.google.protobuf.Descriptors; import com.google.protobuf.Message; @@ -428,7 +429,8 @@ private static ImmutablePair match var i = 1; for (final var expectedRow : expectedAsList) { if (!actual.next()) { - return ImmutablePair.of(ResultSetMatchResult.fail("result does not contain all expected rows."), null); + printCurrentAndRemaining(actual, resultSetPrettyPrinter); + return ImmutablePair.of(ResultSetMatchResult.fail(String.format("result does not contain all expected rows! expected %d rows, got %d", expectedAsList.size(), i - 1)), null); } if (!isMap(expectedRow)) { // I think it should be possible to expect a result set like: [[1,2,3], [4,5,6]]. But ok for now. printCurrentAndRemaining(actual, resultSetPrettyPrinter); @@ -449,20 +451,24 @@ private static ImmutablePair match private static ImmutablePair matchUnorderedResultSet(final RelationalResultSet actual, final @Nonnull Multiset expectedAsMultiSet) throws SQLException { final ResultSetPrettyPrinter resultSetPrettyPrinter = new ResultSetPrettyPrinter(); - var i = 1; - // O(n^2) -- we all got M1s + final var expectedRowCount = expectedAsMultiSet.size(); + var actualRowsCounter = 1; while (actual.next()) { boolean found = false; if (expectedAsMultiSet.isEmpty()) { printCurrentAndRemaining(actual, resultSetPrettyPrinter); - return ImmutablePair.of(ResultSetMatchResult.fail(String.format("too many rows in actual result set! expected %d rows, got %d.", i - 1, i - 1 + resultSetPrettyPrinter.getRowCount())), resultSetPrettyPrinter); + // count the remaining actual rows. + while (actual.next()) { + actualRowsCounter++; + } + return ImmutablePair.of(ResultSetMatchResult.fail(String.format("too many rows in actual result set! expected %d row(s), got %d row(s) instead.", expectedRowCount, actualRowsCounter - 1)), resultSetPrettyPrinter); } - for (final var expectedRow : expectedAsMultiSet) { + for (final var expectedRow : expectedAsMultiSet.elementSet()) { if (!isMap(expectedRow)) { // I think it should be possible to expect a result set like: [[1,2,3], [4,5,6]]. But ok for now. printCurrentAndRemaining(actual, resultSetPrettyPrinter); return ImmutablePair.of(ResultSetMatchResult.fail("unknown format of expected result set"), resultSetPrettyPrinter); } - final var matchResult = matchRow(map(expectedRow), actual.getMetaData().getColumnCount(), valueByName(actual), valueByIndex(actual), i); + final var matchResult = matchRow(map(expectedRow), actual.getMetaData().getColumnCount(), valueByName(actual), valueByIndex(actual), actualRowsCounter); if (matchResult.equals(ResultSetMatchResult.success())) { found = true; expectedAsMultiSet.remove(expectedRow); @@ -471,12 +477,12 @@ private static ImmutablePair match } if (!found) { printCurrentAndRemaining(actual, resultSetPrettyPrinter); - return ImmutablePair.of(ResultSetMatchResult.fail(String.format("result row at %d does not match any expected records", i)), resultSetPrettyPrinter); + return ImmutablePair.of(ResultSetMatchResult.fail(String.format("actual row at %d does not match any expected records", actualRowsCounter)), resultSetPrettyPrinter); } - i++; + actualRowsCounter++; } if (!expectedAsMultiSet.isEmpty()) { - return ImmutablePair.of(ResultSetMatchResult.fail("result does not contain all expected rows"), null); + return ImmutablePair.of(ResultSetMatchResult.fail(String.format("result does not contain all expected rows, expected %d row(s), got %d row(s) instead.", expectedRowCount, actualRowsCounter - 1)), null); } return ImmutablePair.of(ResultSetMatchResult.success(), null); } diff --git a/yaml-tests/src/test/resources/cte.yamsql b/yaml-tests/src/test/resources/cte.yamsql index e2b6aae19f..1c5404c8ab 100644 --- a/yaml-tests/src/test/resources/cte.yamsql +++ b/yaml-tests/src/test/resources/cte.yamsql @@ -119,4 +119,12 @@ test_block: # TODO (CTEs and subqueries are not fully optimized) - query: with c1(x, y) as (select col1, col2 from t1) select x from c1 where y < 3 - explain: "SCAN(<,>) | MAP (_.COL1 AS COL1, _.COL2 AS COL2) | FILTER _.COL2 LESS_THAN promote(@c24 AS LONG) | MAP (_.COL1 AS X)" + - + - query: with c1 as (select col1, col2 from t1) select col1, col2 from c1 + - maxRows: 1 + - result: [{COL1: 10, COL2: 1}] + - result: [{COL1: 10, COL2: 2}] + - result: [{COL1: 20, COL2: 6}] + - result: [{COL1: 20, COL2: 7}] + - result: [] ... diff --git a/yaml-tests/src/test/resources/recursive-cte.yamsql b/yaml-tests/src/test/resources/recursive-cte.yamsql index 0e50900bd2..67ffbdfe59 100644 --- a/yaml-tests/src/test/resources/recursive-cte.yamsql +++ b/yaml-tests/src/test/resources/recursive-cte.yamsql @@ -68,6 +68,49 @@ test_block: {210, 20}, {250, 50}, {250, 50}] + - + - query: with recursive c1 as ( + select id, parent from t1 where parent = -1 + union all + select b.id, b.parent from c1 as a, t1 as b where a.id = b.parent) select id from c1 + - maxRows: 1 + - result: [{ID: 1}] + - result: [{ID: 10}] + - result: [{ID: 20}] + - result: [{ID: 40}] + - result: [{ID: 50}] + - result: [{ID: 70}] + - result: [{ID: 100}] + - result: [{ID: 210}] + - result: [{ID: 250}] + - result: [] + - + - query: with recursive allDescendants as ( + with recursive ancestorsOf250 as ( + select id, parent from t1 where id = 250 + union all + select b.id, b.parent from ancestorsOf250 as a, t1 as b where a.parent = b.id) select id, parent from ancestorsOf250 + union all + select b.id, b.parent from allDescendants as a, t1 as b where a.id = b.parent) select id, parent from allDescendants + - maxRows: 1 + - result: [{250, 50}] + - result: [{50, 10}] + - result: [{10, 1}] + - result: [{1, -1}] + - result: [{10, 1}] + - result: [{20, 1}] + - result: [{40, 10}] + - result: [{50, 10}] + - result: [{70, 10}] + - result: [{250, 50}] + - result: [{40, 10}] + - result: [{50, 10}] + - result: [{70, 10}] + - result: [{100, 20}] + - result: [{210, 20}] + - result: [{250, 50}] + - result: [{250, 50}] + - result: [] # - # does not currently work due to bug in NLJ planning, see https://github.com/FoundationDB/fdb-record-layer/issues/2997 # - query: with recursive c1 as ( From 9c750e7aceaffdd7ea8c8268865157690e6c39ca Mon Sep 17 00:00:00 2001 From: Youssef Hatem Date: Thu, 6 Feb 2025 10:55:36 +0000 Subject: [PATCH 2/3] address comments. --- .../relational/yamltests/Matchers.java | 55 +++++++++---------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/yaml-tests/src/main/java/com/apple/foundationdb/relational/yamltests/Matchers.java b/yaml-tests/src/main/java/com/apple/foundationdb/relational/yamltests/Matchers.java index ef09a49f98..061e68b3bd 100644 --- a/yaml-tests/src/main/java/com/apple/foundationdb/relational/yamltests/Matchers.java +++ b/yaml-tests/src/main/java/com/apple/foundationdb/relational/yamltests/Matchers.java @@ -30,7 +30,6 @@ import com.apple.foundationdb.relational.util.SpotBugsSuppressWarnings; import com.google.common.collect.HashMultiset; -import com.google.common.collect.ImmutableList; import com.google.common.collect.Multiset; import com.google.protobuf.Descriptors; import com.google.protobuf.Message; @@ -64,7 +63,7 @@ public static List arrayList(@Nonnull final Object obj, @Nonnull final String if (obj instanceof List) { return (List) obj; } - fail(String.format("Expecting '%s' to be of type '%s'", desc, List.class.getSimpleName())); + fail(String.format(Locale.ROOT, "Expecting '%s' to be of type '%s'", desc, List.class.getSimpleName())); return null; } @@ -80,7 +79,7 @@ public static List arrayList(@Nonnull final Object obj, @Nonnull final String if (obj instanceof Map) { return (Map) obj; } - fail(String.format("Expecting %s to be of type %s", desc, Map.class.getSimpleName())); + fail(String.format(Locale.ROOT, "Expecting %s to be of type %s", desc, Map.class.getSimpleName())); return null; } @@ -88,7 +87,7 @@ public static List arrayList(@Nonnull final Object obj, @Nonnull final String if (obj instanceof Map.Entry) { return (Map.Entry) obj; } - fail(String.format("Expecting %s to be of type %s", desc, Map.Entry.class.getSimpleName())); + fail(String.format(Locale.ROOT, "Expecting %s to be of type %s", desc, Map.Entry.class.getSimpleName())); return null; } @@ -98,21 +97,21 @@ public static Object first(@Nonnull final List obj) { public static Object first(@Nonnull final List obj, @Nonnull final String desc) { if (obj.isEmpty()) { - fail(String.format("Expecting %s to contain at least one element, however it is empty", desc)); + fail(String.format(Locale.ROOT, "Expecting %s to contain at least one element, however it is empty", desc)); } return obj.get(0); } public static Object second(@Nonnull final List obj) { if (obj.size() <= 1) { - fail(String.format("Expecting %s to contain at least two elements, however it contains %s element", obj, obj.size())); + fail(String.format(Locale.ROOT, "Expecting %s to contain at least two elements, however it contains %s element", obj, obj.size())); } return obj.get(1); } public static Object third(@Nonnull final List obj) { if (obj.size() <= 2) { - fail(String.format("Expecting %s to contain at least three elements, however it contains %s element", obj, obj.size())); + fail(String.format(Locale.ROOT, "Expecting %s to contain at least three elements, however it contains %s element", obj, obj.size())); } return obj.get(2); } @@ -122,7 +121,7 @@ public static String string(@Nonnull final Object obj, @Nonnull final String des // should return null maybe? return (String) obj; } - fail(String.format("Expecting %s to be of type %s, however it is of type %s", desc, String.class.getSimpleName(), obj.getClass().getSimpleName())); + fail(String.format(Locale.ROOT, "Expecting %s to be of type %s, however it is of type %s", desc, String.class.getSimpleName(), obj.getClass().getSimpleName())); return null; } @@ -147,7 +146,7 @@ public static boolean bool(@Nonnull final Object obj) { // should return null maybe? return (Boolean) obj; } - fail(String.format("Expecting %s to be of type %s, however it is of type %s", obj, Boolean.class.getSimpleName(), obj.getClass().getSimpleName())); + fail(String.format(Locale.ROOT, "Expecting %s to be of type %s, however it is of type %s", obj, Boolean.class.getSimpleName(), obj.getClass().getSimpleName())); return false; // never reached. } @@ -162,7 +161,7 @@ public static long longValue(@Nonnull final Object obj) { if (obj instanceof Integer) { return Long.valueOf((Integer) obj); } - fail(String.format("Expecting %s to be of type %s, however it is of type %s", obj, Long.class.getSimpleName(), obj.getClass().getSimpleName())); + fail(String.format(Locale.ROOT, "Expecting %s to be of type %s, however it is of type %s", obj, Long.class.getSimpleName(), obj.getClass().getSimpleName())); return -1; // never reached. } @@ -174,7 +173,7 @@ public static int intValue(@Nonnull final Object obj) { if (obj instanceof Integer) { return (Integer) obj; } - fail(String.format("Expecting %s to be of type %s, however it is of type %s", obj, Integer.class.getSimpleName(), obj.getClass().getSimpleName())); + fail(String.format(Locale.ROOT, "Expecting %s to be of type %s, however it is of type %s", obj, Integer.class.getSimpleName(), obj.getClass().getSimpleName())); return -1; // never reached. } @@ -186,7 +185,7 @@ public static double doubleValue(@Nonnull final Object obj) { if (obj instanceof Double) { return (Double) obj; } - fail(String.format("Expecting %s to be of type %s, however it is of type %s", obj, Double.class.getSimpleName(), obj.getClass().getSimpleName())); + fail(String.format(Locale.ROOT, "Expecting %s to be of type %s, however it is of type %s", obj, Double.class.getSimpleName(), obj.getClass().getSimpleName())); return -1; // never reached. } @@ -208,7 +207,7 @@ public static Message message(@Nonnull final Object obj) { if (obj instanceof Message) { return (Message) obj; } - fail(String.format("Expecting %s to be of type %s, however it is of type %s.", obj, Message.class.getSimpleName(), obj.getClass().getSimpleName())); + fail(String.format(Locale.ROOT, "Expecting %s to be of type %s, however it is of type %s.", obj, Message.class.getSimpleName(), obj.getClass().getSimpleName())); return null; } @@ -216,7 +215,7 @@ public static Message message(@Nonnull final Object obj) { @Nonnull public static T notNull(@Nullable final T object, @Nonnull final String desc) { if (object == null) { - fail(String.format("unexpected %s to be null", desc)); + fail(String.format(Locale.ROOT, "unexpected %s to be null", desc)); } return object; } @@ -227,14 +226,14 @@ public static T notNull(@Nullable final T object, @Nonnull final String desc if (obj instanceof Map) { return ((Map) obj).entrySet().iterator().next(); } - fail(String.format("Expecting %s to be of type %s, however it is of type %s.", desc, Map.class.getSimpleName(), obj.getClass().getSimpleName())); + fail(String.format(Locale.ROOT, "Expecting %s to be of type %s, however it is of type %s.", desc, Map.class.getSimpleName(), obj.getClass().getSimpleName())); return null; } @Nonnull public static Object valueElseKey(@Nonnull final Map.Entry entry) { if (isNull(entry.getKey()) && isNull(entry.getValue())) { - fail(String.format("encountered YAML-style 'null' which is not supported, consider using '%s' instead", CustomTag.NullPlaceholder.INSTANCE)); + fail(String.format(Locale.ROOT, "encountered YAML-style 'null' which is not supported, consider using '%s' instead", CustomTag.NullPlaceholder.INSTANCE)); } return entry.getValue() == null ? entry.getKey() : entry.getValue(); } @@ -430,7 +429,7 @@ private static ImmutablePair match for (final var expectedRow : expectedAsList) { if (!actual.next()) { printCurrentAndRemaining(actual, resultSetPrettyPrinter); - return ImmutablePair.of(ResultSetMatchResult.fail(String.format("result does not contain all expected rows! expected %d rows, got %d", expectedAsList.size(), i - 1)), null); + return ImmutablePair.of(ResultSetMatchResult.fail(String.format(Locale.ROOT, "result does not contain all expected rows! expected %d rows, got %d", expectedAsList.size(), i - 1)), null); } if (!isMap(expectedRow)) { // I think it should be possible to expect a result set like: [[1,2,3], [4,5,6]]. But ok for now. printCurrentAndRemaining(actual, resultSetPrettyPrinter); @@ -444,7 +443,7 @@ private static ImmutablePair match } if (printRemaining(actual, resultSetPrettyPrinter)) { final var leftActualRowCount = resultSetPrettyPrinter.getRowCount(); - return ImmutablePair.of(ResultSetMatchResult.fail(String.format("too many rows in actual result set! expected %d rows, got %d.", expectedAsList.size(), expectedAsList.size() + leftActualRowCount)), resultSetPrettyPrinter); + return ImmutablePair.of(ResultSetMatchResult.fail(String.format(Locale.ROOT, "too many rows in actual result set! expected %d rows, got %d.", expectedAsList.size(), expectedAsList.size() + leftActualRowCount)), resultSetPrettyPrinter); } return ImmutablePair.of(ResultSetMatchResult.success(), null); } @@ -461,7 +460,7 @@ private static ImmutablePair match while (actual.next()) { actualRowsCounter++; } - return ImmutablePair.of(ResultSetMatchResult.fail(String.format("too many rows in actual result set! expected %d row(s), got %d row(s) instead.", expectedRowCount, actualRowsCounter - 1)), resultSetPrettyPrinter); + return ImmutablePair.of(ResultSetMatchResult.fail(String.format(Locale.ROOT, "too many rows in actual result set! expected %d row(s), got %d row(s) instead.", expectedRowCount, actualRowsCounter - 1)), resultSetPrettyPrinter); } for (final var expectedRow : expectedAsMultiSet.elementSet()) { if (!isMap(expectedRow)) { // I think it should be possible to expect a result set like: [[1,2,3], [4,5,6]]. But ok for now. @@ -477,12 +476,12 @@ private static ImmutablePair match } if (!found) { printCurrentAndRemaining(actual, resultSetPrettyPrinter); - return ImmutablePair.of(ResultSetMatchResult.fail(String.format("actual row at %d does not match any expected records", actualRowsCounter)), resultSetPrettyPrinter); + return ImmutablePair.of(ResultSetMatchResult.fail(String.format(Locale.ROOT, "actual row at %d does not match any expected records", actualRowsCounter)), resultSetPrettyPrinter); } actualRowsCounter++; } if (!expectedAsMultiSet.isEmpty()) { - return ImmutablePair.of(ResultSetMatchResult.fail(String.format("result does not contain all expected rows, expected %d row(s), got %d row(s) instead.", expectedRowCount, actualRowsCounter - 1)), null); + return ImmutablePair.of(ResultSetMatchResult.fail(String.format(Locale.ROOT, "result does not contain all expected rows, expected %d row(s), got %d row(s) instead.", expectedRowCount, actualRowsCounter - 1)), null); } return ImmutablePair.of(ResultSetMatchResult.success(), null); } @@ -517,7 +516,7 @@ private static ResultSetMatchResult matchRow(@Nonnull final Map expected, int rowNumber) throws SQLException { final var expectedColCount = expected.entrySet().size(); if (actualEntriesCount != expectedColCount) { - return ResultSetMatchResult.fail(String.format("row cardinality mismatch at %d! expected a row comprising %d column(s), received %d column(s) instead.", rowNumber, expectedColCount, actualEntriesCount)); + return ResultSetMatchResult.fail(String.format(Locale.ROOT, "row cardinality mismatch at %d! expected a row comprising %d column(s), received %d column(s) instead.", rowNumber, expectedColCount, actualEntriesCount)); } return matchMap(expected, actualEntriesCount, entryByNameAccessor, entryByNumberAccessor, rowNumber, ""); } @@ -532,7 +531,7 @@ private static ResultSetMatchResult matchMap(@Nonnull final Map expected, int counter = 1; final var expectedColCount = expected.entrySet().size(); if (actualEntriesCount != expectedColCount) { - return ResultSetMatchResult.fail(String.format("! expected a row comprising %d column(s), received %d column(s) instead.", expectedColCount, actualEntriesCount)); + return ResultSetMatchResult.fail(String.format(Locale.ROOT, "! expected a row comprising %d column(s), received %d column(s) instead.", expectedColCount, actualEntriesCount)); } for (final var entry : expected.entrySet()) { final var expectedField = valueElseKey(entry); @@ -578,7 +577,7 @@ private static ResultSetMatchResult matchField(@Nullable final Object expected, // (nested) message if (expected instanceof Map) { if (!(actual instanceof RelationalStruct)) { - return ResultSetMatchResult.fail(String.format("cell mismatch at row: %d cellRef: %s%n expected šŸŸ¢ to match a struct, got šŸŸ” instead.%nšŸŸ¢ %s (Struct)%nšŸŸ” %s (%s)", rowNumber, cellRef, expected, actual, actual.getClass().getSimpleName())); + return ResultSetMatchResult.fail(String.format(Locale.ROOT, "cell mismatch at row: %d cellRef: %s%n expected šŸŸ¢ to match a struct, got šŸŸ” instead.%nšŸŸ¢ %s (Struct)%nšŸŸ” %s (%s)", rowNumber, cellRef, expected, actual, actual.getClass().getSimpleName())); } final var struct = (RelationalStruct) (actual); return matchMap(map(expected), struct.getAttributes().length, valueByName(struct), valueByIndex(struct), rowNumber, cellRef); @@ -588,13 +587,13 @@ private static ResultSetMatchResult matchField(@Nullable final Object expected, if (expected instanceof List) { final var expectedArray = (List) (expected); if (!(actual instanceof RelationalArray)) { - return ResultSetMatchResult.fail(String.format("cell mismatch at row: %d cellRef: %s%n expected šŸŸ¢ to match an array, got šŸŸ” instead.%nšŸŸ¢ %s (Array)%nšŸŸ” %s (%s)", rowNumber, cellRef, expected, actual, actual.getClass().getSimpleName())); + return ResultSetMatchResult.fail(String.format(Locale.ROOT, "cell mismatch at row: %d cellRef: %s%n expected šŸŸ¢ to match an array, got šŸŸ” instead.%nšŸŸ¢ %s (Array)%nšŸŸ” %s (%s)", rowNumber, cellRef, expected, actual, actual.getClass().getSimpleName())); } final var actualArray = (RelationalArray) (actual); final var actualArrayContent = actualArray.getResultSet(); for (int i = 0; i < expectedArray.size(); i++) { if (!actualArrayContent.next()) { - return ResultSetMatchResult.fail(String.format("cell mismatch at row: %d cellRef: %s%n expected šŸŸ¢ (containing %d array items) does not match šŸŸ” (containing %d array items).%nšŸŸ¢ %s%nšŸŸ” %s", + return ResultSetMatchResult.fail(String.format(Locale.ROOT, "cell mismatch at row: %d cellRef: %s%n expected šŸŸ¢ (containing %d array items) does not match šŸŸ” (containing %d array items).%nšŸŸ¢ %s%nšŸŸ” %s", rowNumber, cellRef, expectedArray.size(), i, expected, actual)); } if (isMap(expectedArray.get(i))) { @@ -649,7 +648,7 @@ private static ResultSetMatchResult matchField(@Nullable final Object expected, if (Objects.equals(expected, actual)) { return ResultSetMatchResult.success(); } else { - return ResultSetMatchResult.fail(String.format("cell mismatch at row: %d cellRef: %s%n expected šŸŸ¢ does not match šŸŸ”.%nšŸŸ¢ %s (%s)%nšŸŸ” %s (%s)", rowNumber, cellRef, expected, expected == null ? "NULL" : expected.getClass().getSimpleName(), actual, actual.getClass().getSimpleName())); + return ResultSetMatchResult.fail(String.format(Locale.ROOT, "cell mismatch at row: %d cellRef: %s%n expected šŸŸ¢ does not match šŸŸ”.%nšŸŸ¢ %s (%s)%nšŸŸ” %s (%s)", rowNumber, cellRef, expected, expected == null ? "NULL" : expected.getClass().getSimpleName(), actual, actual.getClass().getSimpleName())); } } @@ -671,6 +670,6 @@ private static ResultSetMatchResult matchIntField(@Nonnull final Integer expecte return ResultSetMatchResult.success(); } } - return ResultSetMatchResult.fail(String.format("cell mismatch at row: %d cellRef: %s%n expected šŸŸ¢ does not match šŸŸ”.%nšŸŸ¢ %s (Integer) %nšŸŸ” %s (%s)", rowNumber, cellRef, expected, actual, actual.getClass().getSimpleName())); + return ResultSetMatchResult.fail(String.format(Locale.ROOT, "cell mismatch at row: %d cellRef: %s%n expected šŸŸ¢ does not match šŸŸ”.%nšŸŸ¢ %s (Integer) %nšŸŸ” %s (%s)", rowNumber, cellRef, expected, actual, actual.getClass().getSimpleName())); } } From 67def2ebb740612705ba6d417bb6c912a71bf909 Mon Sep 17 00:00:00 2001 From: Youssef Hatem Date: Thu, 6 Feb 2025 18:27:40 +0000 Subject: [PATCH 3/3] set supported version to current. --- yaml-tests/src/test/resources/recursive-cte.yamsql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/yaml-tests/src/test/resources/recursive-cte.yamsql b/yaml-tests/src/test/resources/recursive-cte.yamsql index 67ffbdfe59..59db9bec5a 100644 --- a/yaml-tests/src/test/resources/recursive-cte.yamsql +++ b/yaml-tests/src/test/resources/recursive-cte.yamsql @@ -73,6 +73,7 @@ test_block: select id, parent from t1 where parent = -1 union all select b.id, b.parent from c1 as a, t1 as b where a.id = b.parent) select id from c1 + - supported_version: !current_version - maxRows: 1 - result: [{ID: 1}] - result: [{ID: 10}] @@ -92,6 +93,7 @@ test_block: select b.id, b.parent from ancestorsOf250 as a, t1 as b where a.parent = b.id) select id, parent from ancestorsOf250 union all select b.id, b.parent from allDescendants as a, t1 as b where a.id = b.parent) select id, parent from allDescendants + - supported_version: !current_version - maxRows: 1 - result: [{250, 50}] - result: [{50, 10}]