diff --git a/build/coverage_annotations.py b/build/coverage_annotations.py index 0ddda24ea9..15e6bd9ae6 100644 --- a/build/coverage_annotations.py +++ b/build/coverage_annotations.py @@ -204,15 +204,67 @@ def compute_changed_lines_coverage(lines, changed_line_numbers): return covered_changed, executable_changed +def compute_file_branch_coverage(lines): + """ + Compute overall branch coverage for a file. + + Returns: + tuple of (covered_branches, total_branches) + """ + covered = sum(l.covered_branches for l in lines) + missed = sum(l.missed_branches for l in lines) + return covered, covered + missed + + +def compute_changed_lines_branch_coverage(lines, changed_line_numbers): + """ + Compute branch coverage for only the changed lines in a file. + + Returns: + tuple of (covered_branches, total_branches) + """ + line_map = {l.line_number: l for l in lines} + covered = 0 + total = 0 + + for line_num in changed_line_numbers: + line = line_map.get(line_num) + if line is not None: + covered += line.covered_branches + total += line.covered_branches + line.missed_branches + + return covered, total + + def format_percentage(covered, total): - """Format a coverage percentage string.""" + """Format a line coverage percentage string.""" if total == 0: return 'N/A (no executable lines)' pct = (covered / total) * 100 return f'{pct:.1f}% ({covered}/{total} lines)' -def format_file_annotation(repo_path, file_coverage, changed_coverage, first_changed_line): +def format_branch_percentage(covered, total): + """Format a branch coverage percentage string.""" + pct = (covered / total) * 100 + return f'{pct:.1f}% ({covered}/{total} branches)' + + +def format_combined_percentage(line_cov, branch_cov): + """ + Format combined line + branch coverage. Branch part is omitted when there + are no branches at all (keeps annotations tidy for files with no + conditional logic). + """ + parts = [format_percentage(*line_cov)] + if branch_cov[1] > 0: + parts.append(format_branch_percentage(*branch_cov)) + return ', '.join(parts) + + +def format_file_annotation(repo_path, file_line_coverage, changed_line_coverage, + file_branch_coverage, changed_branch_coverage, + first_changed_line): """ Format a single GitHub Actions annotation for a file's coverage summary. @@ -221,14 +273,11 @@ def format_file_annotation(repo_path, file_coverage, changed_coverage, first_cha Returns the annotation string, or None if there's nothing to report. """ - file_covered, file_total = file_coverage - changed_covered, changed_total = changed_coverage - - file_pct_str = format_percentage(file_covered, file_total) - changed_pct_str = format_percentage(changed_covered, changed_total) + file_pct_str = format_combined_percentage(file_line_coverage, file_branch_coverage) + changed_pct_str = format_combined_percentage(changed_line_coverage, changed_branch_coverage) annotation_line = max(1, first_changed_line - 1) - message = f'File coverage: {file_pct_str} | Changed lines: {changed_pct_str}' + message = f'File coverage: {file_pct_str}%0AChanged lines: {changed_pct_str}' return f'::notice file={repo_path},line={annotation_line}::{message}' @@ -260,10 +309,15 @@ def generate_annotations(coverage_data, diff_data, source_prefixes): file_coverage = compute_file_coverage(lines) changed_coverage = compute_changed_lines_coverage(lines, changed_line_numbers) + file_branch_coverage = compute_file_branch_coverage(lines) + changed_branch_coverage = compute_changed_lines_branch_coverage(lines, changed_line_numbers) first_changed_line = min(changed_line_numbers) annotation = format_file_annotation( - repo_path, file_coverage, changed_coverage, first_changed_line) + repo_path, + file_coverage, changed_coverage, + file_branch_coverage, changed_branch_coverage, + first_changed_line) if annotation: annotations.append(annotation) diff --git a/build/test_coverage_annotations.py b/build/test_coverage_annotations.py index 5ace1c765b..c42afdbe73 100644 --- a/build/test_coverage_annotations.py +++ b/build/test_coverage_annotations.py @@ -30,8 +30,12 @@ sys.path.insert(0, os.path.dirname(__file__)) from coverage_annotations import ( LineCoverage, + compute_changed_lines_branch_coverage, compute_changed_lines_coverage, + compute_file_branch_coverage, compute_file_coverage, + format_branch_percentage, + format_combined_percentage, format_file_annotation, format_percentage, generate_annotations, @@ -343,24 +347,58 @@ def test_no_executable_lines(self): class TestFormatFileAnnotation(unittest.TestCase): """Tests for format_file_annotation()""" - def test_basic_annotation(self): + def test_basic_annotation_no_branches(self): result = format_file_annotation( 'module/src/main/java/com/example/Foo.java', (8, 10), (2, 3), + (0, 0), + (0, 0), + first_changed_line=15, + ) + self.assertEqual( + result, + '::notice file=module/src/main/java/com/example/Foo.java,line=14::' + 'File coverage: 80.0% (8/10 lines)%0AChanged lines: 66.7% (2/3 lines)' + ) + + def test_annotation_with_branches(self): + result = format_file_annotation( + 'module/src/main/java/com/example/Foo.java', + (8, 10), + (2, 3), + (6, 10), + (1, 4), first_changed_line=15, ) self.assertEqual( result, '::notice file=module/src/main/java/com/example/Foo.java,line=14::' - 'File coverage: 80.0% (8/10 lines) | Changed lines: 66.7% (2/3 lines)' + 'File coverage: 80.0% (8/10 lines), 60.0% (6/10 branches)%0A' + 'Changed lines: 66.7% (2/3 lines), 25.0% (1/4 branches)' ) + def test_annotation_omits_branches_when_only_file_has_branches(self): + # File has branches, but changed lines don't touch any + result = format_file_annotation( + 'module/src/main/java/com/example/Foo.java', + (8, 10), + (2, 3), + (6, 10), + (0, 0), + first_changed_line=15, + ) + self.assertIn('80.0% (8/10 lines), 60.0% (6/10 branches)', result) + self.assertIn('Changed lines: 66.7% (2/3 lines)', result) + self.assertNotIn('0/0 branches', result) + def test_annotation_line_does_not_go_below_1(self): result = format_file_annotation( 'module/src/main/java/com/example/Foo.java', (8, 10), (2, 3), + (0, 0), + (0, 0), first_changed_line=1, ) self.assertIn('line=1', result) @@ -370,11 +408,101 @@ def test_no_executable_changed_lines(self): 'module/src/main/java/com/example/Foo.java', (8, 10), (0, 0), + (0, 0), + (0, 0), first_changed_line=5, ) self.assertIn('N/A (no executable lines)', result) +class TestComputeFileBranchCoverage(unittest.TestCase): + """Tests for compute_file_branch_coverage()""" + + def test_mixed_branches(self): + lines = [ + LineCoverage(10, 0, 3, 0, 0), # no branches + LineCoverage(15, 0, 5, 1, 3), # 3 covered, 1 missed + LineCoverage(20, 0, 1, 2, 2), # 2 covered, 2 missed + ] + covered, total = compute_file_branch_coverage(lines) + self.assertEqual(covered, 5) + self.assertEqual(total, 8) + + def test_no_branches(self): + lines = [ + LineCoverage(10, 0, 3, 0, 0), + LineCoverage(11, 0, 2, 0, 0), + ] + covered, total = compute_file_branch_coverage(lines) + self.assertEqual(covered, 0) + self.assertEqual(total, 0) + + def test_all_branches_covered(self): + lines = [LineCoverage(10, 0, 5, 0, 4)] + covered, total = compute_file_branch_coverage(lines) + self.assertEqual(covered, 4) + self.assertEqual(total, 4) + + def test_empty_file(self): + covered, total = compute_file_branch_coverage([]) + self.assertEqual(covered, 0) + self.assertEqual(total, 0) + + +class TestComputeChangedLinesBranchCoverage(unittest.TestCase): + """Tests for compute_changed_lines_branch_coverage()""" + + def test_changed_lines_with_branches(self): + lines = [ + LineCoverage(10, 0, 3, 0, 0), # no branches + LineCoverage(15, 0, 5, 1, 3), # 3 covered, 1 missed + LineCoverage(20, 0, 1, 2, 2), # 2 covered, 2 missed + ] + # Only line 15 is changed + covered, total = compute_changed_lines_branch_coverage(lines, {15}) + self.assertEqual(covered, 3) + self.assertEqual(total, 4) + + def test_changed_lines_without_branches(self): + lines = [LineCoverage(10, 0, 3, 0, 0)] + covered, total = compute_changed_lines_branch_coverage(lines, {10}) + self.assertEqual(covered, 0) + self.assertEqual(total, 0) + + def test_changed_line_not_in_coverage(self): + lines = [LineCoverage(10, 0, 3, 1, 1)] + # Line 5 is changed but has no coverage data (e.g., a comment) + covered, total = compute_changed_lines_branch_coverage(lines, {5}) + self.assertEqual(covered, 0) + self.assertEqual(total, 0) + + +class TestFormatCombinedPercentage(unittest.TestCase): + """Tests for format_combined_percentage()""" + + def test_with_branches(self): + result = format_combined_percentage((4, 8), (3, 5)) + self.assertEqual(result, '50.0% (4/8 lines), 60.0% (3/5 branches)') + + def test_without_branches(self): + result = format_combined_percentage((4, 8), (0, 0)) + self.assertEqual(result, '50.0% (4/8 lines)') + + def test_no_executable_lines(self): + result = format_combined_percentage((0, 0), (0, 0)) + self.assertEqual(result, 'N/A (no executable lines)') + + +class TestFormatBranchPercentage(unittest.TestCase): + """Tests for format_branch_percentage()""" + + def test_basic(self): + self.assertEqual(format_branch_percentage(3, 5), '60.0% (3/5 branches)') + + def test_full(self): + self.assertEqual(format_branch_percentage(4, 4), '100.0% (4/4 branches)') + + class TestGenerateAnnotations(unittest.TestCase): """Tests for generate_annotations()""" @@ -435,9 +563,24 @@ def test_annotation_contains_coverage_data(self): annotations = generate_annotations(self.coverage_data, diff_data, None) self.assertEqual(len(annotations), 1) # File has 8 executable lines, 4 covered -> 50% - self.assertIn('50.0%', annotations[0]) - # Changed lines 12, 13, 14 are all uncovered -> 0% - self.assertIn('0.0%', annotations[0]) + self.assertIn('50.0% (4/8 lines)', annotations[0]) + # File has 4 total branches (line 15: cb=3 mb=1), 3 covered -> 75% + self.assertIn('75.0% (3/4 branches)', annotations[0]) + # Changed lines 12, 13, 14 are all uncovered with no branches -> 0% lines, no branches + self.assertIn('0.0% (0/3 lines)', annotations[0]) + # Changed lines have no branches, so branches segment should be omitted from changed + self.assertNotIn('0/0 branches', annotations[0]) + + def test_annotation_with_branches_on_changed_line(self): + diff_data = { + # Line 15 has cb=3 mb=1 (partial branch coverage) + 'fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/FDBRecordStore.java': {15}, + } + annotations = generate_annotations(self.coverage_data, diff_data, None) + self.assertEqual(len(annotations), 1) + # Changed line 15: 1 covered line, 3/4 branches covered + self.assertIn('100.0% (1/1 lines)', annotations[0]) + self.assertIn('75.0% (3/4 branches)', annotations[0]) class TestEndToEnd(unittest.TestCase): diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/IndexPredicate.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/IndexPredicate.java index 0205363b63..36d7699e5c 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/IndexPredicate.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/IndexPredicate.java @@ -424,8 +424,9 @@ public ConstantPredicate(@Nonnull final com.apple.foundationdb.record.query.plan this.value = ConstantValue.FALSE; } else if (predicate == com.apple.foundationdb.record.query.plan.cascades.predicates.ConstantPredicate.NULL) { this.value = ConstantValue.NULL; + } else { + throw new RecordCoreException("could not create a PoJo constant index predicate").addLogInfo(LogMessageKeys.VALUE, predicate); } - throw new RecordCoreException("could not create a PoJo constant index predicate").addLogInfo(LogMessageKeys.VALUE, predicate); } public ConstantPredicate(@Nonnull final RecordMetaDataProto.ConstantPredicate proto) { diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/predicates/ConstantPredicate.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/predicates/ConstantPredicate.java index 9b7c9386e5..280387c452 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/predicates/ConstantPredicate.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/predicates/ConstantPredicate.java @@ -66,6 +66,19 @@ public class ConstantPredicate extends AbstractQueryPredicate implements LeafQue @Nullable private final Boolean value; + /** + * Returns the {@link ConstantPredicate} singleton corresponding to the given boolean value. + * + * @return {@link #TRUE} for {@code true}, {@link #FALSE} for {@code false}, {@link #NULL} for {@code null} + */ + @Nonnull + public static ConstantPredicate of(@Nullable final Boolean value) { + if (value == null) { + return NULL; + } + return value ? TRUE : FALSE; + } + public ConstantPredicate(@Nonnull final PlanSerializationContext serializationContext, @Nonnull final PConstantPredicate constantPredicateProto) { super(serializationContext, Objects.requireNonNull(constantPredicateProto.getSuper())); diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Expression.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Expression.java index e91b5ed750..6f58d9558c 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Expression.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/Expression.java @@ -22,10 +22,15 @@ import com.apple.foundationdb.annotation.API; import com.apple.foundationdb.record.EvaluationContext; +import com.apple.foundationdb.record.query.expressions.Comparisons; import com.apple.foundationdb.record.query.plan.cascades.AliasMap; import com.apple.foundationdb.record.query.plan.cascades.Column; import com.apple.foundationdb.record.query.plan.cascades.CorrelationIdentifier; +import com.apple.foundationdb.record.query.plan.cascades.predicates.ConstantPredicate; import com.apple.foundationdb.record.query.plan.cascades.predicates.QueryPredicate; +import com.apple.foundationdb.record.query.plan.cascades.predicates.ValuePredicate; +import com.apple.foundationdb.record.query.plan.cascades.typing.Type; +import com.apple.foundationdb.record.query.plan.cascades.typing.TypeRepository; import com.apple.foundationdb.record.query.plan.cascades.values.AggregateValue; import com.apple.foundationdb.record.query.plan.cascades.values.AndOrValue; import com.apple.foundationdb.record.query.plan.cascades.values.ArithmeticValue; @@ -33,9 +38,11 @@ import com.apple.foundationdb.record.query.plan.cascades.values.ConstantObjectValue; import com.apple.foundationdb.record.query.plan.cascades.values.LiteralValue; import com.apple.foundationdb.record.query.plan.cascades.values.NotValue; +import com.apple.foundationdb.record.query.plan.cascades.values.NullValue; import com.apple.foundationdb.record.query.plan.cascades.values.RecordConstructorValue; import com.apple.foundationdb.record.query.plan.cascades.values.RelOpValue; import com.apple.foundationdb.record.query.plan.cascades.values.Value; +import com.apple.foundationdb.relational.api.exceptions.ErrorCode; import com.apple.foundationdb.relational.api.metadata.DataType; import com.apple.foundationdb.relational.recordlayer.metadata.DataTypeUtils; import com.apple.foundationdb.relational.util.Assert; @@ -351,18 +358,45 @@ private static Iterable filterUnderlying(@Nonnull final Expression expres .collect(ImmutableList.toImmutableList()); } + /** + * Converts a boolean-typed {@link Expression} into a {@link QueryPredicate} suitable for use as a + * {@code WHERE} or {@code ON} predicate. If the underlying value already implements {@link BooleanValue} + * (for example, an {@code AND}, {@code OR}, comparison, or {@code NOT} expression), it converts itself. + * Otherwise, the value may be a SQL {@code NULL} ({@link NullValue}), a {@code BOOLEAN}-typed literal, + * constant reference, parameter, or column. A {@code NullValue} folds to {@link ConstantPredicate#NULL}. + * A literal ({@link LiteralValue}) folds to the corresponding {@link ConstantPredicate}. Everything + * else is wrapped as a {@code ValuePredicate} performing a {@code «value» = TRUE} comparison. + */ @Nonnull public static QueryPredicate toUnderlyingPredicate(@Nonnull final Expression expression, @Nonnull final Set localAliases, boolean forDdl) { - final var value = Assert.castUnchecked(expression.getUnderlying(), BooleanValue.class); - final Optional result; - if (forDdl) { - result = value.toQueryPredicate(ParseHelpers.EMPTY_TYPE_REPOSITORY, localAliases); - } else { - result = value.toQueryPredicate(null, localAliases); + final Value value = expression.getUnderlying(); + + // A `BooleanValue` can convert itself into a `QueryPredicate`. + if (value instanceof final BooleanValue booleanValue) { + final TypeRepository typeRepository = forDdl ? ParseHelpers.EMPTY_TYPE_REPOSITORY : null; + final Optional result = booleanValue.toQueryPredicate(typeRepository, localAliases); + return Assert.optionalUnchecked(result); + } + + // Recognize `NullValue` as a null boolean `ConstantPredicate`. + if (value instanceof NullValue) { + return ConstantPredicate.NULL; } - return Assert.optionalUnchecked(result); + + // At this point the `value` is some other boolean expression that does not implement `BooleanValue`. + Assert.thatUnchecked(value.getResultType().getTypeCode() == Type.TypeCode.BOOLEAN, + ErrorCode.DATATYPE_MISMATCH, + () -> "expected boolean expression but got " + value.getResultType()); + + // Convert a plain boolean `LiteralValue` to `ConstantPredicate`. + if (value instanceof final LiteralValue literalValue) { + return ConstantPredicate.of((Boolean) literalValue.getLiteralValue()); + } + + // For other cases, lift the expression into a `ValuePredicate` performing a `«value» = TRUE` comparison. + return new ValuePredicate(value, new Comparisons.SimpleComparison(Comparisons.Type.EQUALS, true)); } } diff --git a/yaml-tests/src/test/java/YamlIntegrationTests.java b/yaml-tests/src/test/java/YamlIntegrationTests.java index bad50efda3..f42b76bf15 100644 --- a/yaml-tests/src/test/java/YamlIntegrationTests.java +++ b/yaml-tests/src/test/java/YamlIntegrationTests.java @@ -105,6 +105,11 @@ void booleanTypes(YamlTest.Runner runner) throws Exception { runner.runYamsql("boolean.yamsql"); } + @TestTemplate + void boolLiteralPredicate(YamlTest.Runner runner) throws Exception { + runner.runYamsql("boolean-ddl.yamsql"); + } + @TestTemplate void bytes(YamlTest.Runner runner) throws Exception { runner.runYamsql("bytes.yamsql"); diff --git a/yaml-tests/src/test/resources/boolean-ddl.yamsql b/yaml-tests/src/test/resources/boolean-ddl.yamsql new file mode 100644 index 0000000000..69dd92ca35 --- /dev/null +++ b/yaml-tests/src/test/resources/boolean-ddl.yamsql @@ -0,0 +1,43 @@ +# +# boolean-ddl.yamsql +# +# This source file is part of the FoundationDB open source project +# +# Copyright 2021-2026 Apple Inc. and the FoundationDB project authors +# +# Licensed 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. + +--- +options: + supported_version: !current_version +--- +# Exercise boolean constants (TRUE/FALSE/NULL) used as top-level WHERE predicates in `CREATE INDEX … AS` DDL statements. +# This covers the `forDdl == true` branch of `Expression.Utils.toUnderlyingPredicate()`. +schema_template: + CREATE TABLE T ("id" INTEGER, "col1" INTEGER, PRIMARY KEY ("id")) + CREATE INDEX idx_true AS SELECT "col1" FROM T WHERE TRUE ORDER BY "col1" + CREATE INDEX idx_false AS SELECT "col1" FROM T WHERE FALSE ORDER BY "col1" + CREATE INDEX idx_null AS SELECT "col1" FROM T WHERE NULL ORDER BY "col1" +--- +setup: + steps: + - query: INSERT INTO T VALUES (1, 100) +--- +test_block: + preset: single_repetition_ordered + tests: + - + # Just confirm the table is usable. + - query: SELECT "col1" FROM T ORDER BY "col1" + - result: [{col1: 100}] +... diff --git a/yaml-tests/src/test/resources/join-tests.metrics.binpb b/yaml-tests/src/test/resources/join-tests.metrics.binpb index d519a09d65..72ee229e9c 100644 --- a/yaml-tests/src/test/resources/join-tests.metrics.binpb +++ b/yaml-tests/src/test/resources/join-tests.metrics.binpb @@ -1,7 +1,7 @@ /  unnamed-2EXPLAIN select fname, lname from emp inner join project on emp_id = emp.id inner join dept on dept_id = dept.id and dept.name = 'Sales';. -ޤE (y0Ȟ8@+SCAN([IS DEPT]) | FILTER _.NAME EQUALS promote(@c29 AS STRING) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER q1.EMP_ID EQUALS _.ID AND _.DEPT_ID EQUALS q0.ID AS q2 RETURN q2 } AS q2 RETURN (q2.FNAME AS FNAME, q2.LNAME AS LNAME) },digraph G { +P #(y08@+SCAN([IS DEPT]) | FILTER _.NAME EQUALS promote(@c29 AS STRING) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER q1.EMP_ID EQUALS _.ID AND _.DEPT_ID EQUALS q0.ID AS q2 RETURN q2 } AS q2 RETURN (q2.FNAME AS FNAME, q2.LNAME AS LNAME) },digraph G { fontname=courier; rankdir=BT; splines=line; @@ -10,46 +10,46 @@ 3 [ label=<
Scan
comparisons: [IS DEPT]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME)" ]; 4 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME)" ]; 5 [ label=<
Nested Loop Join
FLATMAP q2
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS FNAME, STRING AS LNAME, LONG AS DEPT_ID)" ]; - 6 [ label=<
Predicate Filter
WHERE q6.EMP_ID EQUALS q2.ID AND q2.DEPT_ID EQUALS q10.ID
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS FNAME, STRING AS LNAME, LONG AS DEPT_ID)" ]; - 7 [ label=<
Scan
comparisons: [IS PROJECT]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME, STRING AS DSC, LONG AS EMP_ID)" ]; - 8 [ label=<
Scan
comparisons: [IS EMP]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS FNAME, STRING AS LNAME, LONG AS DEPT_ID)" ]; - 9 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME, STRING AS DSC, LONG AS EMP_ID)" ]; + 6 [ label=<
Scan
comparisons: [IS PROJECT]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME, STRING AS DSC, LONG AS EMP_ID)" ]; + 7 [ label=<
Predicate Filter
WHERE q6.EMP_ID EQUALS q2.ID AND q2.DEPT_ID EQUALS q10.ID
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS FNAME, STRING AS LNAME, LONG AS DEPT_ID)" ]; + 8 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME, STRING AS DSC, LONG AS EMP_ID)" ]; + 9 [ label=<
Scan
comparisons: [IS EMP]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS FNAME, STRING AS LNAME, LONG AS DEPT_ID)" ]; 10 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS FNAME, STRING AS LNAME, LONG AS DEPT_ID)" ]; 3 -> 2 [ label=< q10> label="q10" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 4 -> 3 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 2 -> 1 [ label=< q10> label="q10" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 6 -> 5 [ label=< q2> label="q2" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 7 -> 5 [ label=< q6> label="q6" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 8 -> 6 [ label=< q2> label="q2" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 9 -> 7 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 10 -> 8 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 6 -> 5 [ label=< q6> label="q6" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 7 -> 5 [ label=< q2> label="q2" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 8 -> 6 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 9 -> 7 [ label=< q2> label="q2" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 10 -> 9 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 5 -> 1 [ label=< q2> label="q2" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; { - 6 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 7 -> 5 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { - 5 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + rank=same; + rankDir=LR; + 6 -> 7 [ color="red" style="invis" ]; } { 2 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { - rank=same; - rankDir=LR; - 2 -> 5 [ color="red" style="invis" ]; + 7 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { - 6 -> 5 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 5 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { rank=same; rankDir=LR; - 7 -> 6 [ color="red" style="invis" ]; + 2 -> 5 [ color="red" style="invis" ]; } })  unnamed-2wEXPLAIN select dept.name, project.name from emp, dept, project where emp.dept_id = dept.id and project.emp_id = emp.id;( - @ (`08@ SCAN([IS PROJECT]) | FLATMAP q0 -> { SCAN([IS DEPT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q0.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.NAME AS _0, q0.NAME AS _1) }&digraph G { + 7 (`08@ SCAN([IS PROJECT]) | FLATMAP q0 -> { SCAN([IS DEPT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q0.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.NAME AS _0, q0.NAME AS _1) }&digraph G { fontname=courier; rankdir=BT; splines=line; @@ -89,10 +89,10 @@ rankDir=LR; 2 -> 4 [ color="red" style="invis" ]; } -}) +}*  - unnamed-2EXPLAIN select dept.name, project.name from emp inner join dept on emp.dept_id = dept.id inner join project on project.emp_id = emp.id;( - G (`08@ SCAN([IS PROJECT]) | FLATMAP q0 -> { SCAN([IS DEPT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q0.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.NAME AS _0, q0.NAME AS _1) }&digraph G { + unnamed-2EXPLAIN select dept.name, project.name from emp inner join dept on emp.dept_id = dept.id inner join project on project.emp_id = emp.id;( + ȟ S(`08@ SCAN([IS PROJECT]) | FLATMAP q0 -> { SCAN([IS DEPT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q0.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.NAME AS _0, q0.NAME AS _1) }&digraph G { fontname=courier; rankdir=BT; splines=line; @@ -100,42 +100,42 @@ 2 [ label=<
Scan
comparisons: [IS PROJECT]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME, STRING AS DSC, LONG AS EMP_ID)" ]; 3 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME, STRING AS DSC, LONG AS EMP_ID)" ]; 4 [ label=<
Nested Loop Join
FLATMAP q6
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME)" ]; - 5 [ label=<
Predicate Filter
WHERE q2.DEPT_ID EQUALS q6.ID AND q10.EMP_ID EQUALS q2.ID
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS FNAME, STRING AS LNAME, LONG AS DEPT_ID)" ]; - 6 [ label=<
Scan
comparisons: [IS DEPT]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME)" ]; - 7 [ label=<
Scan
comparisons: [IS EMP]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS FNAME, STRING AS LNAME, LONG AS DEPT_ID)" ]; - 8 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME)" ]; + 5 [ label=<
Scan
comparisons: [IS DEPT]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME)" ]; + 6 [ label=<
Predicate Filter
WHERE q2.DEPT_ID EQUALS q6.ID AND q10.EMP_ID EQUALS q2.ID
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS FNAME, STRING AS LNAME, LONG AS DEPT_ID)" ]; + 7 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME)" ]; + 8 [ label=<
Scan
comparisons: [IS EMP]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS FNAME, STRING AS LNAME, LONG AS DEPT_ID)" ]; 9 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS FNAME, STRING AS LNAME, LONG AS DEPT_ID)" ]; 3 -> 2 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 2 -> 1 [ label=< q10> label="q10" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 5 -> 4 [ label=< q2> label="q2" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 6 -> 4 [ label=< q6> label="q6" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 7 -> 5 [ label=< q2> label="q2" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 8 -> 6 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 9 -> 7 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 5 -> 4 [ label=< q6> label="q6" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 6 -> 4 [ label=< q2> label="q2" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 7 -> 5 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 8 -> 6 [ label=< q2> label="q2" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 9 -> 8 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 4 -> 1 [ label=< q6> label="q6" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; { - 5 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 6 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { - rank=same; - rankDir=LR; - 6 -> 5 [ color="red" style="invis" ]; + 4 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { - 5 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + rank=same; + rankDir=LR; + 2 -> 4 [ color="red" style="invis" ]; } { - 4 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 6 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { rank=same; rankDir=LR; - 2 -> 4 [ color="red" style="invis" ]; + 5 -> 6 [ color="red" style="invis" ]; } }*  unnamed-2EXPLAIN select * from (select dept.name, project.name from emp, dept, project where emp.dept_id = dept.id and project.emp_id = emp.id) X;( - ѧ: (b0ڦ8@ SCAN([IS PROJECT]) | FLATMAP q0 -> { SCAN([IS DEPT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q0.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.NAME AS _0, q0.NAME AS _1) }&digraph G { + 7 ذ(b08@ SCAN([IS PROJECT]) | FLATMAP q0 -> { SCAN([IS DEPT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q0.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.NAME AS _0, q0.NAME AS _1) }&digraph G { fontname=courier; rankdir=BT; splines=line; @@ -157,28 +157,28 @@ 9 -> 8 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 4 -> 1 [ label=< q6> label="q6" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; { - 6 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; - } - { - 4 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 6 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { rank=same; rankDir=LR; - 2 -> 4 [ color="red" style="invis" ]; + 5 -> 6 [ color="red" style="invis" ]; } { - 6 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 6 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + } + { + 4 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { rank=same; rankDir=LR; - 5 -> 6 [ color="red" style="invis" ]; + 2 -> 4 [ color="red" style="invis" ]; } }*  unnamed-2EXPLAIN select (*) from (select dept.name, project.name from emp, dept, project where emp.dept_id = dept.id and project.emp_id = emp.id) X;) - ˮ3 (b08@ SCAN([IS DEPT]) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q0.ID AND q1.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN ((q0.NAME AS _0, q1.NAME AS _1) AS _0) }'digraph G { + Ŝ0 (b08@ SCAN([IS DEPT]) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q0.ID AND q1.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN ((q0.NAME AS _0, q1.NAME AS _1) AS _0) }'digraph G { fontname=courier; rankdir=BT; splines=line; @@ -200,28 +200,28 @@ 9 -> 8 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 4 -> 1 [ label=< q10> label="q10" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; { - 6 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 6 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { - rank=same; - rankDir=LR; - 5 -> 6 [ color="red" style="invis" ]; + 4 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { - 6 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + rank=same; + rankDir=LR; + 2 -> 4 [ color="red" style="invis" ]; } { - 4 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 6 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { rank=same; rankDir=LR; - 2 -> 4 [ color="red" style="invis" ]; + 5 -> 6 [ color="red" style="invis" ]; } }+  unnamed-2EXPLAIN select dept.name, project.name from project inner join emp on emp.id = project.emp_id inner join dept on emp.dept_id = dept.id;* - ꀞ1 ݴ(e08@SCAN([IS DEPT]) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP, EQUALS q1.EMP_ID]) | FILTER _.DEPT_ID EQUALS q0.ID AS q2 RETURN q1 } AS q1 RETURN (q0.NAME AS _0, q1.NAME AS _1) }(digraph G { + . (e0ͩ8@SCAN([IS DEPT]) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP, EQUALS q1.EMP_ID]) | FILTER _.DEPT_ID EQUALS q0.ID AS q2 RETURN q1 } AS q1 RETURN (q0.NAME AS _0, q1.NAME AS _1) }(digraph G { fontname=courier; rankdir=BT; splines=line; @@ -243,34 +243,34 @@ 9 -> 8 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 4 -> 1 [ label=< q2> label="q2" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; { - 8 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 8 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { - 6 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 6 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { - rank=same; - rankDir=LR; - 5 -> 6 [ color="red" style="invis" ]; + 4 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { - 8 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + rank=same; + rankDir=LR; + 2 -> 4 [ color="red" style="invis" ]; } { - 6 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 8 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { - 4 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 6 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { rank=same; rankDir=LR; - 2 -> 4 [ color="red" style="invis" ]; + 5 -> 6 [ color="red" style="invis" ]; } }/  unnamed-2EXPLAIN select dept.id, dept.name, project.name from emp, dept, project where emp.dept_id = dept.id and project.emp_id = emp.id and dept.id not in (1). -̽U ֗(j08@-SCAN([IS DEPT]) | FILTER NOT _.ID IN promote(@c40 AS ARRAY(LONG)) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q0.ID AND q1.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q0.ID AS ID, q0.NAME AS _1, q1.NAME AS _2) },digraph G { +. (j0ߍ8@-SCAN([IS DEPT]) | FILTER NOT _.ID IN promote(@c40 AS ARRAY(LONG)) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q0.ID AND q1.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q0.ID AS ID, q0.NAME AS _1, q1.NAME AS _2) },digraph G { fontname=courier; rankdir=BT; splines=line; @@ -294,31 +294,31 @@ 10 -> 9 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 5 -> 1 [ label=< q10> label="q10" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; { - 7 -> 5 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 7 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { - rank=same; - rankDir=LR; - 6 -> 7 [ color="red" style="invis" ]; + 5 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { 2 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { - 7 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + rank=same; + rankDir=LR; + 2 -> 5 [ color="red" style="invis" ]; } { - 5 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 7 -> 5 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { rank=same; rankDir=LR; - 2 -> 5 [ color="red" style="invis" ]; + 6 -> 7 [ color="red" style="invis" ]; } }0  unnamed-2EXPLAIN select dept.id, dept.name, project.name from emp inner join dept on emp.dept_id = dept.id and dept.id not in (1) inner join project on project.emp_id = emp.id. -Ϛ5 (j0ۘ8@-SCAN([IS DEPT]) | FILTER NOT _.ID IN promote(@c31 AS ARRAY(LONG)) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q0.ID AND q1.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q0.ID AS ID, q0.NAME AS _1, q1.NAME AS _2) },digraph G { +4 (j08@-SCAN([IS DEPT]) | FILTER NOT _.ID IN promote(@c31 AS ARRAY(LONG)) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q0.ID AND q1.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q0.ID AS ID, q0.NAME AS _1, q1.NAME AS _2) },digraph G { fontname=courier; rankdir=BT; splines=line; @@ -342,31 +342,31 @@ 10 -> 9 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 5 -> 1 [ label=< q10> label="q10" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; { - 2 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 7 -> 5 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { - 7 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + rank=same; + rankDir=LR; + 6 -> 7 [ color="red" style="invis" ]; } { - 5 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 2 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { - rank=same; - rankDir=LR; - 2 -> 5 [ color="red" style="invis" ]; + 7 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { - 7 -> 5 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 5 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { rank=same; rankDir=LR; - 6 -> 7 [ color="red" style="invis" ]; + 2 -> 5 [ color="red" style="invis" ]; } }1  unnamed-2EXPLAIN select project.id, project.name from emp, dept, project where emp.dept_id = dept.id and project.emp_id = emp.id and dept.id not in (3) and project.id not in (3)/ -B (08@?SCAN([IS EMP]) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FILTER NOT _.ID IN promote(@c36 AS ARRAY(LONG)) AND _.EMP_ID EQUALS q0.ID | FLATMAP q1 -> { SCAN([IS DEPT]) | FILTER NOT _.ID IN promote(@c36 AS ARRAY(LONG)) AND q0.DEPT_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.ID AS ID, q1.NAME AS NAME) }-digraph G { +] +(08@?SCAN([IS EMP]) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FILTER NOT _.ID IN promote(@c36 AS ARRAY(LONG)) AND _.EMP_ID EQUALS q0.ID | FLATMAP q1 -> { SCAN([IS DEPT]) | FILTER NOT _.ID IN promote(@c36 AS ARRAY(LONG)) AND q0.DEPT_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.ID AS ID, q1.NAME AS NAME) }-digraph G { fontname=courier; rankdir=BT; splines=line; @@ -374,18 +374,18 @@ 2 [ label=<
Scan
comparisons: [IS EMP]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS FNAME, STRING AS LNAME, LONG AS DEPT_ID)" ]; 3 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS FNAME, STRING AS LNAME, LONG AS DEPT_ID)" ]; 4 [ label=<
Nested Loop Join
FLATMAP q10
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME, STRING AS DSC, LONG AS EMP_ID)" ]; - 5 [ label=<
Predicate Filter
WHERE NOT q10.ID IN promote(@c36 AS ARRAY(LONG)) AND q10.EMP_ID EQUALS q2.ID
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME, STRING AS DSC, LONG AS EMP_ID)" ]; - 6 [ label=<
Predicate Filter
WHERE NOT q6.ID IN promote(@c36 AS ARRAY(LONG)) AND q2.DEPT_ID EQUALS q6.ID
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME)" ]; - 7 [ label=<
Scan
comparisons: [IS PROJECT]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME, STRING AS DSC, LONG AS EMP_ID)" ]; - 8 [ label=<
Scan
comparisons: [IS DEPT]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME)" ]; - 9 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME, STRING AS DSC, LONG AS EMP_ID)" ]; - 10 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME)" ]; + 5 [ label=<
Predicate Filter
WHERE NOT q6.ID IN promote(@c36 AS ARRAY(LONG)) AND q2.DEPT_ID EQUALS q6.ID
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME)" ]; + 6 [ label=<
Predicate Filter
WHERE NOT q10.ID IN promote(@c36 AS ARRAY(LONG)) AND q10.EMP_ID EQUALS q2.ID
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME, STRING AS DSC, LONG AS EMP_ID)" ]; + 7 [ label=<
Scan
comparisons: [IS DEPT]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME)" ]; + 8 [ label=<
Scan
comparisons: [IS PROJECT]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME, STRING AS DSC, LONG AS EMP_ID)" ]; + 9 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME)" ]; + 10 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME, STRING AS DSC, LONG AS EMP_ID)" ]; 3 -> 2 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 2 -> 1 [ label=< q2> label="q2" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 5 -> 4 [ label=< q10> label="q10" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 6 -> 4 [ label=< q6> label="q6" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 7 -> 5 [ label=< q10> label="q10" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 8 -> 6 [ label=< q6> label="q6" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 5 -> 4 [ label=< q6> label="q6" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 6 -> 4 [ label=< q10> label="q10" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 7 -> 5 [ label=< q6> label="q6" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 8 -> 6 [ label=< q10> label="q10" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 9 -> 7 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 10 -> 8 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 4 -> 1 [ label=< q10> label="q10" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; @@ -398,7 +398,7 @@ { rank=same; rankDir=LR; - 5 -> 6 [ color="red" style="invis" ]; + 6 -> 5 [ color="red" style="invis" ]; } { 5 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; @@ -417,14 +417,14 @@ }3  unnamed-2EXPLAIN select dept.id, dept.name, project.name from emp, dept, project where emp.dept_id = dept.id and project.emp_id = emp.id and dept.id in (1, 2)1 -v՜5 \(0V8@[IN arrayDistinct(promote(@c39 AS ARRAY(LONG)))] | INJOIN q0 -> { SCAN([IS DEPT, EQUALS q0]) } | FLATMAP q1 -> { SCAN([IS PROJECT]) | FLATMAP q2 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q2.EMP_ID EQUALS _.ID AS q3 RETURN q2 } AS q2 RETURN (q1.ID AS ID, q1.NAME AS _1, q2.NAME AS _2) }/digraph G { +vڬ5 a(0R8@[IN arrayDistinct(promote(@c39 AS ARRAY(LONG)))] | INJOIN q0 -> { SCAN([IS DEPT, EQUALS q0]) } | FLATMAP q1 -> { SCAN([IS PROJECT]) | FLATMAP q2 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q2.EMP_ID EQUALS _.ID AS q3 RETURN q2 } AS q2 RETURN (q1.ID AS ID, q1.NAME AS _1, q2.NAME AS _2) }/digraph G { fontname=courier; rankdir=BT; splines=line; 1 [ label=<
Nested Loop Join
FLATMAP (q6.ID AS ID, q6.NAME AS _1, q10.NAME AS _2)
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS _1, STRING AS _2)" ]; 2 [ label=<
Nested Loop Join
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="12" tooltip="RELATION(LONG AS ID, STRING AS NAME)" ]; - 3 [ label=<
Table Function
EXPLODE(arrayDistinct(promote(@c39 AS ARRAY(LONG))))
> color="black" shape="plain" style="filled" fillcolor="darkseagreen2" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME)" ]; - 4 [ label=<
Scan
comparisons: [IS DEPT, EQUALS q396]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME)" ]; + 3 [ label=<
Scan
comparisons: [IS DEPT, EQUALS q396]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME)" ]; + 4 [ label=<
Table Function
EXPLODE(arrayDistinct(promote(@c39 AS ARRAY(LONG))))
> color="black" shape="plain" style="filled" fillcolor="darkseagreen2" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME)" ]; 5 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME)" ]; 6 [ label=<
Nested Loop Join
FLATMAP q10
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME, STRING AS DSC, LONG AS EMP_ID)" ]; 7 [ label=<
Scan
comparisons: [IS PROJECT]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME, STRING AS DSC, LONG AS EMP_ID)" ]; @@ -434,7 +434,7 @@ 11 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS FNAME, STRING AS LNAME, LONG AS DEPT_ID)" ]; 3 -> 2 [ color="black" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 4 -> 2 [ color="black" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 5 -> 4 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 5 -> 3 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 2 -> 1 [ label=< q6> label="q6" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 7 -> 6 [ label=< q10> label="q10" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 8 -> 6 [ label=< q2> label="q2" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; @@ -442,14 +442,6 @@ 10 -> 8 [ label=< q2> label="q2" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 11 -> 10 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 6 -> 1 [ label=< q10> label="q10" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - { - 8 -> 6 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; - } - { - rank=same; - rankDir=LR; - 7 -> 8 [ color="red" style="invis" ]; - } { 8 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } @@ -464,12 +456,20 @@ { rank=same; rankDir=LR; - 3 -> 4 [ color="red" style="invis" ]; + 4 -> 3 [ color="red" style="invis" ]; + } + { + 8 -> 6 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + } + { + rank=same; + rankDir=LR; + 7 -> 8 [ color="red" style="invis" ]; } }" J unnamed-2=EXPLAIN select * from ja join jb using(c1) join jd using(c1);" - 5 ߣ(O08@SCAN([IS JD]) | FLATMAP q0 -> { SCAN([IS JB]) | FLATMAP q1 -> { SCAN([IS JA, EQUALS q1.C1]) AS q2 RETURN (q2 AS _0, q1 AS _1) } AS q3 RETURN (q3._0.C1 AS C1, q3._0.C2 AS C2, q3._1.C3 AS C3, q0.C4 AS C4) } digraph G { + J (O08@SCAN([IS JD]) | FLATMAP q0 -> { SCAN([IS JB]) | FLATMAP q1 -> { SCAN([IS JA, EQUALS q1.C1]) AS q2 RETURN (q2 AS _0, q1 AS _1) } AS q3 RETURN (q3._0.C1 AS C1, q3._0.C2 AS C2, q3._1.C3 AS C3, q0.C4 AS C4) } digraph G { fontname=courier; rankdir=BT; splines=line; @@ -488,23 +488,23 @@ J 7 -> 5 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 8 -> 6 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 4 -> 1 [ label=< q53> label="q53" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - { - 6 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; - } { rank=same; rankDir=LR; - 5 -> 6 [ color="red" style="invis" ]; + 2 -> 4 [ color="red" style="invis" ]; + } + { + 6 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { rank=same; rankDir=LR; - 2 -> 4 [ color="red" style="invis" ]; + 5 -> 6 [ color="red" style="invis" ]; } }# b unnamed-2UEXPLAIN select jua.c5, jub.c5, jud.c5 from jua join jub using(c1) join jud using(c1);" - Q (O08@SCAN([IS JUD]) | FLATMAP q0 -> { SCAN([IS JUB]) | FLATMAP q1 -> { SCAN([IS JUA, EQUALS q1.C1]) AS q2 RETURN (q2 AS _0, q1 AS _1) } AS q3 RETURN (q3._0.C5 AS _0, q3._1.C5 AS _1, q0.C5 AS _2) }!digraph G { + * (O08@SCAN([IS JUD]) | FLATMAP q0 -> { SCAN([IS JUB]) | FLATMAP q1 -> { SCAN([IS JUA, EQUALS q1.C1]) AS q2 RETURN (q2 AS _0, q1 AS _1) } AS q3 RETURN (q3._0.C5 AS _0, q3._1.C5 AS _1, q0.C5 AS _2) }!digraph G { fontname=courier; rankdir=BT; splines=line; @@ -523,23 +523,23 @@ b 7 -> 5 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 8 -> 6 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 4 -> 1 [ label=< q53> label="q53" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - { - 5 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; - } { rank=same; rankDir=LR; - 6 -> 5 [ color="red" style="invis" ]; + 2 -> 4 [ color="red" style="invis" ]; + } + { + 5 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { rank=same; rankDir=LR; - 2 -> 4 [ color="red" style="invis" ]; + 6 -> 5 [ color="red" style="invis" ]; } }& c unnamed-2VEXPLAIN select * from jua join (select * from jub join jud using(c1)) as X using (c1);% - ԁS (a0≍8@SCAN([IS JUD]) | FLATMAP q0 -> { SCAN([IS JUB, EQUALS q0.C1]) | FLATMAP q1 -> { SCAN([IS JUA, EQUALS q1.C1]) AS q2 RETURN (q2 AS _0, q1 AS _1) } AS q3 RETURN (q3._0.C1 AS C1, q3._0.C2 AS C2, q3._0.C5 AS _2, q3._1.C3 AS C3, q3._1.C5 AS _4, q0.C4 AS C4, q0.C5 AS _6) }"digraph G { + B 䮓(a08@SCAN([IS JUD]) | FLATMAP q0 -> { SCAN([IS JUB, EQUALS q0.C1]) | FLATMAP q1 -> { SCAN([IS JUA, EQUALS q1.C1]) AS q2 RETURN (q2 AS _0, q1 AS _1) } AS q3 RETURN (q3._0.C1 AS C1, q3._0.C2 AS C2, q3._0.C5 AS _2, q3._1.C3 AS C3, q3._1.C5 AS _4, q0.C4 AS C4, q0.C5 AS _6) }"digraph G { fontname=courier; rankdir=BT; splines=line; @@ -574,10 +574,146 @@ c rankDir=LR; 6 -> 5 [ color="red" style="invis" ]; } +} +N + unnamed-2AEXPLAIN select ja.c1, ja.c2, jb.c3 from ja inner join jb on true; +ƨX @(&082@dSCAN([IS JA]) | FLATMAP q0 -> { SCAN([IS JB]) AS q1 RETURN (q0.C1 AS C1, q0.C2 AS C2, q1.C3 AS C3) }digraph G { + fontname=courier; + rankdir=BT; + splines=line; + 1 [ label=<
Nested Loop Join
FLATMAP (q2.C1 AS C1, q2.C2 AS C2, q6.C3 AS C3)
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2, LONG AS C3)" ]; + 2 [ label=<
Scan
comparisons: [IS JA]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2)" ]; + 3 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2)" ]; + 4 [ label=<
Scan
comparisons: [IS JB]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3)" ]; + 5 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3)" ]; + 3 -> 2 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 2 -> 1 [ label=< q2> label="q2" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 5 -> 4 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 4 -> 1 [ label=< q6> label="q6" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + { + rank=same; + rankDir=LR; + 2 -> 4 [ color="red" style="invis" ]; + } +} +G + unnamed-2:EXPLAIN select ja.c1, ja.c2, jb.c3 from ja, jb where true; + (&0׿82@dSCAN([IS JA]) | FLATMAP q0 -> { SCAN([IS JB]) AS q1 RETURN (q0.C1 AS C1, q0.C2 AS C2, q1.C3 AS C3) }digraph G { + fontname=courier; + rankdir=BT; + splines=line; + 1 [ label=<
Nested Loop Join
FLATMAP (q2.C1 AS C1, q2.C2 AS C2, q6.C3 AS C3)
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2, LONG AS C3)" ]; + 2 [ label=<
Scan
comparisons: [IS JA]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2)" ]; + 3 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2)" ]; + 4 [ label=<
Scan
comparisons: [IS JB]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3)" ]; + 5 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3)" ]; + 3 -> 2 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 2 -> 1 [ label=< q2> label="q2" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 5 -> 4 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 4 -> 1 [ label=< q6> label="q6" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + { + rank=same; + rankDir=LR; + 2 -> 4 [ color="red" style="invis" ]; + } +} +O + unnamed-2BEXPLAIN select ja.c1, ja.c2, jb.c3 from ja inner join jb on false; +  (&0-86@sSCAN([IS JA]) | FLATMAP q0 -> { SCAN([IS JB]) | FILTER false AS q1 RETURN (q0.C1 AS C1, q0.C2 AS C2, q1.C3 AS C3) }digraph G { + fontname=courier; + rankdir=BT; + splines=line; + 1 [ label=<
Nested Loop Join
FLATMAP (q2.C1 AS C1, q2.C2 AS C2, q6.C3 AS C3)
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2, LONG AS C3)" ]; + 2 [ label=<
Scan
comparisons: [IS JA]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2)" ]; + 3 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2)" ]; + 4 [ label=<
Predicate Filter
WHERE false
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3)" ]; + 5 [ label=<
Scan
comparisons: [IS JB]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3)" ]; + 6 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3)" ]; + 3 -> 2 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 2 -> 1 [ label=< q2> label="q2" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 5 -> 4 [ label=< q6> label="q6" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 6 -> 5 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 4 -> 1 [ label=< q6> label="q6" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + { + rank=same; + rankDir=LR; + 2 -> 4 [ color="red" style="invis" ]; + } +} +H + unnamed-2;EXPLAIN select ja.c1, ja.c2, jb.c3 from ja, jb where false; +ԧ ڡ(&0486@sSCAN([IS JA]) | FLATMAP q0 -> { SCAN([IS JB]) | FILTER false AS q1 RETURN (q0.C1 AS C1, q0.C2 AS C2, q1.C3 AS C3) }digraph G { + fontname=courier; + rankdir=BT; + splines=line; + 1 [ label=<
Nested Loop Join
FLATMAP (q2.C1 AS C1, q2.C2 AS C2, q6.C3 AS C3)
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2, LONG AS C3)" ]; + 2 [ label=<
Scan
comparisons: [IS JA]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2)" ]; + 3 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2)" ]; + 4 [ label=<
Predicate Filter
WHERE false
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3)" ]; + 5 [ label=<
Scan
comparisons: [IS JB]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3)" ]; + 6 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3)" ]; + 3 -> 2 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 2 -> 1 [ label=< q2> label="q2" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 5 -> 4 [ label=< q6> label="q6" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 6 -> 5 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 4 -> 1 [ label=< q6> label="q6" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + { + rank=same; + rankDir=LR; + 2 -> 4 [ color="red" style="invis" ]; + } +} +_ + unnamed-2REXPLAIN select ja.c1, ja.c2, jb.c3 from ja inner join jb on cast(null as boolean); + + ($0 81@SCAN([IS JB]) | FILTER CAST(NULL AS BOOLEAN) EQUALS true | FLATMAP q0 -> { SCAN([IS JA]) AS q1 RETURN (q1.C1 AS C1, q1.C2 AS C2, q0.C3 AS C3) }digraph G { + fontname=courier; + rankdir=BT; + splines=line; + 1 [ label=<
Nested Loop Join
FLATMAP (q2.C1 AS C1, q2.C2 AS C2, q6.C3 AS C3)
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2, LONG AS C3)" ]; + 2 [ label=<
Predicate Filter
WHERE CAST(NULL AS BOOLEAN) EQUALS true
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3)" ]; + 3 [ label=<
Scan
comparisons: [IS JB]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3)" ]; + 4 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3)" ]; + 5 [ label=<
Scan
comparisons: [IS JA]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2)" ]; + 6 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2)" ]; + 3 -> 2 [ label=< q6> label="q6" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 4 -> 3 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 2 -> 1 [ label=< q6> label="q6" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 6 -> 5 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 5 -> 1 [ label=< q2> label="q2" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + { + rank=same; + rankDir=LR; + 2 -> 5 [ color="red" style="invis" ]; + } +} +X + unnamed-2KEXPLAIN select ja.c1, ja.c2, jb.c3 from ja, jb where cast(null as boolean); + +($0P81@SCAN([IS JB]) | FILTER CAST(NULL AS BOOLEAN) EQUALS true | FLATMAP q0 -> { SCAN([IS JA]) AS q1 RETURN (q1.C1 AS C1, q1.C2 AS C2, q0.C3 AS C3) }digraph G { + fontname=courier; + rankdir=BT; + splines=line; + 1 [ label=<
Nested Loop Join
FLATMAP (q2.C1 AS C1, q2.C2 AS C2, q6.C3 AS C3)
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2, LONG AS C3)" ]; + 2 [ label=<
Predicate Filter
WHERE CAST(NULL AS BOOLEAN) EQUALS true
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3)" ]; + 3 [ label=<
Scan
comparisons: [IS JB]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3)" ]; + 4 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3)" ]; + 5 [ label=<
Scan
comparisons: [IS JA]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2)" ]; + 6 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2)" ]; + 3 -> 2 [ label=< q6> label="q6" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 4 -> 3 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 2 -> 1 [ label=< q6> label="q6" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 6 -> 5 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 5 -> 1 [ label=< q2> label="q2" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + { + rank=same; + rankDir=LR; + 2 -> 5 [ color="red" style="invis" ]; + } }/  "three-way-joins-right-deep-plannerEXPLAIN select fname, lname from emp inner join project on emp_id = emp.id inner join dept on dept_id = dept.id and dept.name = 'Sales';. -# (M08@SCAN([IS DEPT]) | FILTER _.NAME EQUALS promote(@c29 AS STRING) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER q1.EMP_ID EQUALS _.ID AND _.DEPT_ID EQUALS q0.ID AS q2 RETURN q2 } AS q2 RETURN (q2.FNAME AS FNAME, q2.LNAME AS LNAME) },digraph G { +0 ߲(M08@SCAN([IS DEPT]) | FILTER _.NAME EQUALS promote(@c29 AS STRING) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER q1.EMP_ID EQUALS _.ID AND _.DEPT_ID EQUALS q0.ID AS q2 RETURN q2 } AS q2 RETURN (q2.FNAME AS FNAME, q2.LNAME AS LNAME) },digraph G { fontname=courier; rankdir=BT; splines=line; @@ -600,14 +736,6 @@ c 9 -> 7 [ label=< q2> label="q2" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 10 -> 9 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 5 -> 1 [ label=< q2> label="q2" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - { - 7 -> 5 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; - } - { - rank=same; - rankDir=LR; - 6 -> 7 [ color="red" style="invis" ]; - } { 2 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } @@ -622,10 +750,18 @@ c rankDir=LR; 2 -> 5 [ color="red" style="invis" ]; } + { + 7 -> 5 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + } + { + rank=same; + rankDir=LR; + 6 -> 7 [ color="red" style="invis" ]; + } }*  "three-way-joins-right-deep-plannerwEXPLAIN select dept.name, project.name from emp, dept, project where emp.dept_id = dept.id and project.emp_id = emp.id;( -& (E0ݜ8r@SCAN([IS PROJECT]) | FLATMAP q0 -> { SCAN([IS DEPT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q0.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.NAME AS _0, q0.NAME AS _1) }&digraph G { +) Ϻ(E08r@SCAN([IS PROJECT]) | FLATMAP q0 -> { SCAN([IS DEPT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q0.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.NAME AS _0, q0.NAME AS _1) }&digraph G { fontname=courier; rankdir=BT; splines=line; @@ -647,28 +783,28 @@ c 9 -> 8 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 4 -> 1 [ label=< q6> label="q6" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; { - 6 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 6 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { - rank=same; - rankDir=LR; - 5 -> 6 [ color="red" style="invis" ]; + 4 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { - 6 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + rank=same; + rankDir=LR; + 2 -> 4 [ color="red" style="invis" ]; } { - 4 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 6 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { rank=same; rankDir=LR; - 2 -> 4 [ color="red" style="invis" ]; + 5 -> 6 [ color="red" style="invis" ]; } -}* +}*  -"three-way-joins-right-deep-plannerEXPLAIN select dept.name, project.name from emp inner join dept on emp.dept_id = dept.id inner join project on project.emp_id = emp.id;( -1 (E08r@SCAN([IS PROJECT]) | FLATMAP q0 -> { SCAN([IS DEPT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q0.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.NAME AS _0, q0.NAME AS _1) }&digraph G { +"three-way-joins-right-deep-plannerEXPLAIN select dept.name, project.name from emp inner join dept on emp.dept_id = dept.id inner join project on project.emp_id = emp.id;( +  ‚(E0]8r@SCAN([IS PROJECT]) | FLATMAP q0 -> { SCAN([IS DEPT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q0.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.NAME AS _0, q0.NAME AS _1) }&digraph G { fontname=courier; rankdir=BT; splines=line; @@ -690,28 +826,28 @@ c 9 -> 7 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 4 -> 1 [ label=< q6> label="q6" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; { - 5 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 5 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { - rank=same; - rankDir=LR; - 6 -> 5 [ color="red" style="invis" ]; + 4 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { - 5 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + rank=same; + rankDir=LR; + 2 -> 4 [ color="red" style="invis" ]; } { - 4 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 5 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { rank=same; rankDir=LR; - 2 -> 4 [ color="red" style="invis" ]; + 6 -> 5 [ color="red" style="invis" ]; } }*  "three-way-joins-right-deep-plannerEXPLAIN select * from (select dept.name, project.name from emp, dept, project where emp.dept_id = dept.id and project.emp_id = emp.id) X;( -( (G0Ɔ8v@SCAN([IS PROJECT]) | FLATMAP q0 -> { SCAN([IS DEPT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q0.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.NAME AS _0, q0.NAME AS _1) }&digraph G { +' (G0ѕ8v@SCAN([IS PROJECT]) | FLATMAP q0 -> { SCAN([IS DEPT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q0.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.NAME AS _0, q0.NAME AS _1) }&digraph G { fontname=courier; rankdir=BT; splines=line; @@ -751,10 +887,10 @@ c rankDir=LR; 2 -> 4 [ color="red" style="invis" ]; } -}* +}*  -"three-way-joins-right-deep-plannerEXPLAIN select (*) from (select dept.name, project.name from emp, dept, project where emp.dept_id = dept.id and project.emp_id = emp.id) X;) -) (G08v@SCAN([IS DEPT]) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q0.ID AND q1.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN ((q0.NAME AS _0, q1.NAME AS _1) AS _0) }'digraph G { +"three-way-joins-right-deep-plannerEXPLAIN select (*) from (select dept.name, project.name from emp, dept, project where emp.dept_id = dept.id and project.emp_id = emp.id) X;) + (G0f8v@SCAN([IS DEPT]) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q0.ID AND q1.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN ((q0.NAME AS _0, q1.NAME AS _1) AS _0) }'digraph G { fontname=courier; rankdir=BT; splines=line; @@ -762,42 +898,42 @@ c 2 [ label=<
Scan
comparisons: [IS DEPT]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME)" ]; 3 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME)" ]; 4 [ label=<
Nested Loop Join
FLATMAP q10
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME, STRING AS DSC, LONG AS EMP_ID)" ]; - 5 [ label=<
Scan
comparisons: [IS PROJECT]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME, STRING AS DSC, LONG AS EMP_ID)" ]; - 6 [ label=<
Predicate Filter
WHERE q2.DEPT_ID EQUALS q6.ID AND q10.EMP_ID EQUALS q2.ID
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS FNAME, STRING AS LNAME, LONG AS DEPT_ID)" ]; - 7 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME, STRING AS DSC, LONG AS EMP_ID)" ]; - 8 [ label=<
Scan
comparisons: [IS EMP]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS FNAME, STRING AS LNAME, LONG AS DEPT_ID)" ]; + 5 [ label=<
Predicate Filter
WHERE q2.DEPT_ID EQUALS q6.ID AND q10.EMP_ID EQUALS q2.ID
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS FNAME, STRING AS LNAME, LONG AS DEPT_ID)" ]; + 6 [ label=<
Scan
comparisons: [IS PROJECT]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME, STRING AS DSC, LONG AS EMP_ID)" ]; + 7 [ label=<
Scan
comparisons: [IS EMP]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS FNAME, STRING AS LNAME, LONG AS DEPT_ID)" ]; + 8 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS NAME, STRING AS DSC, LONG AS EMP_ID)" ]; 9 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, STRING AS FNAME, STRING AS LNAME, LONG AS DEPT_ID)" ]; 3 -> 2 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 2 -> 1 [ label=< q6> label="q6" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 5 -> 4 [ label=< q10> label="q10" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 6 -> 4 [ label=< q2> label="q2" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 7 -> 5 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 8 -> 6 [ label=< q2> label="q2" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 9 -> 8 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 5 -> 4 [ label=< q2> label="q2" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 6 -> 4 [ label=< q10> label="q10" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 7 -> 5 [ label=< q2> label="q2" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 8 -> 6 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 9 -> 7 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 4 -> 1 [ label=< q10> label="q10" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; { - 6 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; - } - { - 4 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 5 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { rank=same; rankDir=LR; - 2 -> 4 [ color="red" style="invis" ]; + 6 -> 5 [ color="red" style="invis" ]; } { - 6 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 5 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + } + { + 4 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { rank=same; rankDir=LR; - 5 -> 6 [ color="red" style="invis" ]; + 2 -> 4 [ color="red" style="invis" ]; } },  "three-way-joins-right-deep-plannerEXPLAIN select dept.name, project.name from project inner join emp on emp.id = project.emp_id inner join dept on emp.dept_id = dept.id;* -䙏2 (I08{@SCAN([IS DEPT]) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP, EQUALS q1.EMP_ID]) | FILTER _.DEPT_ID EQUALS q0.ID AS q2 RETURN q1 } AS q1 RETURN (q0.NAME AS _0, q1.NAME AS _1) }(digraph G { +Ǖ+ (I08{@SCAN([IS DEPT]) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP, EQUALS q1.EMP_ID]) | FILTER _.DEPT_ID EQUALS q0.ID AS q2 RETURN q1 } AS q1 RETURN (q0.NAME AS _0, q1.NAME AS _1) }(digraph G { fontname=courier; rankdir=BT; splines=line; @@ -846,7 +982,7 @@ c }0  "three-way-joins-right-deep-plannerEXPLAIN select dept.id, dept.name, project.name from emp, dept, project where emp.dept_id = dept.id and project.emp_id = emp.id and dept.id not in (1). -ɐ$ (K0օ8@SCAN([IS DEPT]) | FILTER NOT _.ID IN promote(@c40 AS ARRAY(LONG)) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q0.ID AND q1.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q0.ID AS ID, q0.NAME AS _1, q1.NAME AS _2) },digraph G { +2 ޫ(K0˼8@SCAN([IS DEPT]) | FILTER NOT _.ID IN promote(@c40 AS ARRAY(LONG)) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q0.ID AND q1.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q0.ID AS ID, q0.NAME AS _1, q1.NAME AS _2) },digraph G { fontname=courier; rankdir=BT; splines=line; @@ -869,14 +1005,6 @@ c 9 -> 7 [ label=< q2> label="q2" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 10 -> 9 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 5 -> 1 [ label=< q10> label="q10" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - { - 7 -> 5 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; - } - { - rank=same; - rankDir=LR; - 6 -> 7 [ color="red" style="invis" ]; - } { 2 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } @@ -891,10 +1019,18 @@ c rankDir=LR; 2 -> 5 [ color="red" style="invis" ]; } + { + 7 -> 5 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + } + { + rank=same; + rankDir=LR; + 6 -> 7 [ color="red" style="invis" ]; + } }0  "three-way-joins-right-deep-plannerEXPLAIN select dept.id, dept.name, project.name from emp inner join dept on emp.dept_id = dept.id and dept.id not in (1) inner join project on project.emp_id = emp.id. -) (K08@SCAN([IS DEPT]) | FILTER NOT _.ID IN promote(@c31 AS ARRAY(LONG)) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q0.ID AND q1.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q0.ID AS ID, q0.NAME AS _1, q1.NAME AS _2) },digraph G { +3 (K08@SCAN([IS DEPT]) | FILTER NOT _.ID IN promote(@c31 AS ARRAY(LONG)) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q0.ID AND q1.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q0.ID AS ID, q0.NAME AS _1, q1.NAME AS _2) },digraph G { fontname=courier; rankdir=BT; splines=line; @@ -918,31 +1054,32 @@ c 10 -> 9 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 5 -> 1 [ label=< q10> label="q10" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; { - 7 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 7 -> 5 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { - 5 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + rank=same; + rankDir=LR; + 6 -> 7 [ color="red" style="invis" ]; } { - 2 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 7 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { - rank=same; - rankDir=LR; - 2 -> 5 [ color="red" style="invis" ]; + 5 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { - 7 -> 5 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 2 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { rank=same; rankDir=LR; - 6 -> 7 [ color="red" style="invis" ]; + 2 -> 5 [ color="red" style="invis" ]; } -}1 +}1  -"three-way-joins-right-deep-plannerEXPLAIN select project.id, project.name from emp, dept, project where emp.dept_id = dept.id and project.emp_id = emp.id and dept.id not in (3) and project.id not in (3)/ - ʞ. ۹(Q08@SCAN([IS EMP]) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FILTER NOT _.ID IN promote(@c36 AS ARRAY(LONG)) AND _.EMP_ID EQUALS q0.ID | FLATMAP q1 -> { SCAN([IS DEPT]) | FILTER NOT _.ID IN promote(@c36 AS ARRAY(LONG)) AND q0.DEPT_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.ID AS ID, q1.NAME AS NAME) }-digraph G { +"three-way-joins-right-deep-plannerEXPLAIN select project.id, project.name from emp, dept, project where emp.dept_id = dept.id and project.emp_id = emp.id and dept.id not in (3) and project.id not in (3)/ +  +(Q0˽}8@SCAN([IS EMP]) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FILTER NOT _.ID IN promote(@c36 AS ARRAY(LONG)) AND _.EMP_ID EQUALS q0.ID | FLATMAP q1 -> { SCAN([IS DEPT]) | FILTER NOT _.ID IN promote(@c36 AS ARRAY(LONG)) AND q0.DEPT_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.ID AS ID, q1.NAME AS NAME) }-digraph G { fontname=courier; rankdir=BT; splines=line; @@ -993,8 +1130,7 @@ c }3  "three-way-joins-right-deep-plannerEXPLAIN select dept.id, dept.name, project.name from emp, dept, project where emp.dept_id = dept.id and project.emp_id = emp.id and dept.id in (1, 2)1 -& 0(0 -8@f[IN arrayDistinct(promote(@c39 AS ARRAY(LONG)))] | INJOIN q0 -> { SCAN([IS DEPT, EQUALS q0]) } | FLATMAP q1 -> { SCAN([IS PROJECT]) | FLATMAP q2 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q2.EMP_ID EQUALS _.ID AS q3 RETURN q2 } AS q2 RETURN (q1.ID AS ID, q1.NAME AS _1, q2.NAME AS _2) }/digraph G { +& 8(08@f[IN arrayDistinct(promote(@c39 AS ARRAY(LONG)))] | INJOIN q0 -> { SCAN([IS DEPT, EQUALS q0]) } | FLATMAP q1 -> { SCAN([IS PROJECT]) | FLATMAP q2 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q2.EMP_ID EQUALS _.ID AS q3 RETURN q2 } AS q2 RETURN (q1.ID AS ID, q1.NAME AS _1, q2.NAME AS _2) }/digraph G { fontname=courier; rankdir=BT; splines=line; @@ -1019,6 +1155,14 @@ c 10 -> 8 [ label=< q2> label="q2" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 11 -> 10 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 6 -> 1 [ label=< q10> label="q10" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + { + 8 -> 6 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + } + { + rank=same; + rankDir=LR; + 7 -> 8 [ color="red" style="invis" ]; + } { rank=same; rankDir=LR; @@ -1035,18 +1179,10 @@ c rankDir=LR; 2 -> 6 [ color="red" style="invis" ]; } - { - 8 -> 6 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; - } - { - rank=same; - rankDir=LR; - 7 -> 8 [ color="red" style="invis" ]; - } }# c "three-way-joins-right-deep-planner=EXPLAIN select * from ja join jb using(c1) join jd using(c1);" -4 (@08g@ SCAN([IS JD]) | FLATMAP q0 -> { SCAN([IS JB]) | FLATMAP q1 -> { SCAN([IS JA, EQUALS q1.C1]) AS q2 RETURN (q2 AS _0, q1 AS _1) } AS q3 RETURN (q3._0.C1 AS C1, q3._0.C2 AS C2, q3._1.C3 AS C3, q0.C4 AS C4) } digraph G { +/ Ğ (@0ի8g@ SCAN([IS JD]) | FLATMAP q0 -> { SCAN([IS JB]) | FLATMAP q1 -> { SCAN([IS JA, EQUALS q1.C1]) AS q2 RETURN (q2 AS _0, q1 AS _1) } AS q3 RETURN (q3._0.C1 AS C1, q3._0.C2 AS C2, q3._1.C3 AS C3, q0.C4 AS C4) } digraph G { fontname=courier; rankdir=BT; splines=line; @@ -1054,34 +1190,35 @@ c 2 [ label=<
Scan
comparisons: [IS JD]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C4)" ]; 3 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C4)" ]; 4 [ label=<
Nested Loop Join
FLATMAP (q2 AS _0, q6 AS _1)
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2 AS _0, LONG AS C1, LONG AS C3 AS _1)" ]; - 5 [ label=<
Scan
comparisons: [IS JA, EQUALS q6.C1]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2)" ]; - 6 [ label=<
Scan
comparisons: [IS JB]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3)" ]; - 7 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2)" ]; - 8 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3)" ]; + 5 [ label=<
Scan
comparisons: [IS JB]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3)" ]; + 6 [ label=<
Scan
comparisons: [IS JA, EQUALS q6.C1]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2)" ]; + 7 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3)" ]; + 8 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2)" ]; 3 -> 2 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 2 -> 1 [ label=< q10> label="q10" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 5 -> 4 [ label=< q2> label="q2" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 6 -> 4 [ label=< q6> label="q6" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 5 -> 4 [ label=< q6> label="q6" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 6 -> 4 [ label=< q2> label="q2" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 7 -> 5 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 8 -> 6 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 4 -> 1 [ label=< q47> label="q47" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; { - 5 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 6 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { rank=same; rankDir=LR; - 6 -> 5 [ color="red" style="invis" ]; + 5 -> 6 [ color="red" style="invis" ]; } { rank=same; rankDir=LR; 2 -> 4 [ color="red" style="invis" ]; } -}# +}# { -"three-way-joins-right-deep-plannerUEXPLAIN select jua.c5, jub.c5, jud.c5 from jua join jub using(c1) join jud using(c1);" -5 (@08g@ SCAN([IS JUD]) | FLATMAP q0 -> { SCAN([IS JUB]) | FLATMAP q1 -> { SCAN([IS JUA, EQUALS q1.C1]) AS q2 RETURN (q2 AS _0, q1 AS _1) } AS q3 RETURN (q3._0.C5 AS _0, q3._1.C5 AS _1, q0.C5 AS _2) }!digraph G { +"three-way-joins-right-deep-plannerUEXPLAIN select jua.c5, jub.c5, jud.c5 from jua join jub using(c1) join jud using(c1);" +灼 ߕ +(@0n8g@ SCAN([IS JUD]) | FLATMAP q0 -> { SCAN([IS JUB]) | FLATMAP q1 -> { SCAN([IS JUA, EQUALS q1.C1]) AS q2 RETURN (q2 AS _0, q1 AS _1) } AS q3 RETURN (q3._0.C5 AS _0, q3._1.C5 AS _1, q0.C5 AS _2) }!digraph G { fontname=courier; rankdir=BT; splines=line; @@ -1116,7 +1253,7 @@ c }& | "three-way-joins-right-deep-plannerVEXPLAIN select * from jua join (select * from jub join jud using(c1)) as X using (c1);% -A (N0݉8@ SCAN([IS JUD]) | FLATMAP q0 -> { SCAN([IS JUB, EQUALS q0.C1]) | FLATMAP q1 -> { SCAN([IS JUA, EQUALS q1.C1]) AS q2 RETURN (q2 AS _0, q1 AS _1) } AS q3 RETURN (q3._0.C1 AS C1, q3._0.C2 AS C2, q3._0.C5 AS _2, q3._1.C3 AS C3, q3._1.C5 AS _4, q0.C4 AS C4, q0.C5 AS _6) }"digraph G { +5 ͕(N0玖8@ SCAN([IS JUD]) | FLATMAP q0 -> { SCAN([IS JUB, EQUALS q0.C1]) | FLATMAP q1 -> { SCAN([IS JUA, EQUALS q1.C1]) AS q2 RETURN (q2 AS _0, q1 AS _1) } AS q3 RETURN (q3._0.C1 AS C1, q3._0.C2 AS C2, q3._0.C5 AS _2, q3._1.C3 AS C3, q3._1.C5 AS _4, q0.C4 AS C4, q0.C5 AS _6) }"digraph G { fontname=courier; rankdir=BT; splines=line; @@ -1124,27 +1261,27 @@ c 2 [ label=<
Scan
comparisons: [IS JUD]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C4, LONG AS C5)" ]; 3 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C4, LONG AS C5)" ]; 4 [ label=<
Nested Loop Join
FLATMAP (q2 AS _0, q6 AS _1)
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2, LONG AS C5 AS _0, LONG AS C1, LONG AS C3, LONG AS C5 AS _1)" ]; - 5 [ label=<
Scan
comparisons: [IS JUB, EQUALS q10.C1]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3, LONG AS C5)" ]; - 6 [ label=<
Scan
comparisons: [IS JUA, EQUALS q6.C1]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2, LONG AS C5)" ]; - 7 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3, LONG AS C5)" ]; - 8 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2, LONG AS C5)" ]; + 5 [ label=<
Scan
comparisons: [IS JUA, EQUALS q6.C1]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2, LONG AS C5)" ]; + 6 [ label=<
Scan
comparisons: [IS JUB, EQUALS q10.C1]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3, LONG AS C5)" ]; + 7 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C2, LONG AS C5)" ]; + 8 [ label=<
Primary Storage
record types: [A, PROJECT, B, JUB, JA, JUA, JB, JUD, EMP, DEPT, JD]
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS C1, LONG AS C3, LONG AS C5)" ]; 3 -> 2 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 2 -> 1 [ label=< q10> label="q10" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 5 -> 4 [ label=< q6> label="q6" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 6 -> 4 [ label=< q2> label="q2" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 5 -> 4 [ label=< q2> label="q2" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 6 -> 4 [ label=< q6> label="q6" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 7 -> 5 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 8 -> 6 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 4 -> 1 [ label=< q51> label="q51" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; { - 6 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 5 -> 4 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { rank=same; rankDir=LR; - 5 -> 6 [ color="red" style="invis" ]; + 6 -> 5 [ color="red" style="invis" ]; } { - 5 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; + 6 -> 1 [ color="blue" style="dotted" arrowhead="none" tailport="nw" headport="s" constraint="false" ]; } { rank=same; diff --git a/yaml-tests/src/test/resources/join-tests.metrics.yaml b/yaml-tests/src/test/resources/join-tests.metrics.yaml index 80083d0ea6..7e743a127f 100644 --- a/yaml-tests/src/test/resources/join-tests.metrics.yaml +++ b/yaml-tests/src/test/resources/join-tests.metrics.yaml @@ -7,9 +7,9 @@ unnamed-2: EQUALS _.ID AND _.DEPT_ID EQUALS q0.ID AS q2 RETURN q2 } AS q2 RETURN (q2.FNAME AS FNAME, q2.LNAME AS LNAME) } task_count: 2056 - task_total_time_ms: 146 + task_total_time_ms: 169 transform_count: 856 - transform_time_ms: 48 + transform_time_ms: 74 transform_yield_count: 121 insert_time_ms: 11 insert_new_count: 232 @@ -21,11 +21,11 @@ unnamed-2: { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q0.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.NAME AS _0, q0.NAME AS _1) } task_count: 1574 - task_total_time_ms: 136 + task_total_time_ms: 116 transform_count: 655 - transform_time_ms: 41 + transform_time_ms: 54 transform_yield_count: 96 - insert_time_ms: 6 + insert_time_ms: 10 insert_new_count: 172 insert_reused_count: 32 - query: EXPLAIN select dept.name, project.name from emp inner join dept on emp.dept_id @@ -35,11 +35,11 @@ unnamed-2: { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q0.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.NAME AS _0, q0.NAME AS _1) } task_count: 1574 - task_total_time_ms: 149 + task_total_time_ms: 334 transform_count: 655 - transform_time_ms: 46 + transform_time_ms: 174 transform_yield_count: 96 - insert_time_ms: 8 + insert_time_ms: 37 insert_new_count: 172 insert_reused_count: 32 - query: EXPLAIN select dept.name, project.name from emp inner join dept on emp.dept_id @@ -49,11 +49,11 @@ unnamed-2: { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q0.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.NAME AS _0, q0.NAME AS _1) } task_count: 1574 - task_total_time_ms: 149 + task_total_time_ms: 334 transform_count: 655 - transform_time_ms: 46 + transform_time_ms: 174 transform_yield_count: 96 - insert_time_ms: 8 + insert_time_ms: 37 insert_new_count: 172 insert_reused_count: 32 - query: EXPLAIN select * from (select dept.name, project.name from emp, dept, project @@ -63,9 +63,9 @@ unnamed-2: { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q0.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.NAME AS _0, q0.NAME AS _1) } task_count: 1604 - task_total_time_ms: 122 + task_total_time_ms: 116 transform_count: 659 - transform_time_ms: 39 + transform_time_ms: 53 transform_yield_count: 98 insert_time_ms: 6 insert_new_count: 176 @@ -77,11 +77,11 @@ unnamed-2: { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q0.ID AND q1.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN ((q0.NAME AS _0, q1.NAME AS _1) AS _0) } task_count: 1604 - task_total_time_ms: 107 + task_total_time_ms: 101 transform_count: 659 - transform_time_ms: 28 + transform_time_ms: 40 transform_yield_count: 98 - insert_time_ms: 5 + insert_time_ms: 6 insert_new_count: 176 insert_reused_count: 32 - query: EXPLAIN select dept.name, project.name from project inner join emp on emp.id @@ -91,11 +91,11 @@ unnamed-2: { SCAN([IS EMP, EQUALS q1.EMP_ID]) | FILTER _.DEPT_ID EQUALS q0.ID AS q2 RETURN q1 } AS q1 RETURN (q0.NAME AS _0, q1.NAME AS _1) } task_count: 1617 - task_total_time_ms: 103 + task_total_time_ms: 97 transform_count: 657 - transform_time_ms: 32 + transform_time_ms: 33 transform_yield_count: 101 - insert_time_ms: 5 + insert_time_ms: 4 insert_new_count: 187 insert_reused_count: 27 - query: EXPLAIN select dept.id, dept.name, project.name from emp, dept, project @@ -107,11 +107,11 @@ unnamed-2: EQUALS q0.ID AND q1.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q0.ID AS ID, q0.NAME AS _1, q1.NAME AS _2) } task_count: 1804 - task_total_time_ms: 179 + task_total_time_ms: 98 transform_count: 765 - transform_time_ms: 63 + transform_time_ms: 44 transform_yield_count: 106 - insert_time_ms: 10 + insert_time_ms: 8 insert_new_count: 198 insert_reused_count: 45 - query: EXPLAIN select dept.id, dept.name, project.name from emp inner join dept @@ -123,9 +123,9 @@ unnamed-2: EQUALS q0.ID AND q1.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q0.ID AS ID, q0.NAME AS _1, q1.NAME AS _2) } task_count: 1804 - task_total_time_ms: 112 + task_total_time_ms: 109 transform_count: 765 - transform_time_ms: 40 + transform_time_ms: 41 transform_yield_count: 106 insert_time_ms: 6 insert_new_count: 198 @@ -140,11 +140,11 @@ unnamed-2: EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.ID AS ID, q1.NAME AS NAME) } task_count: 2320 - task_total_time_ms: 139 + task_total_time_ms: 196 transform_count: 996 - transform_time_ms: 38 + transform_time_ms: 90 transform_yield_count: 131 - insert_time_ms: 12 + insert_time_ms: 13 insert_new_count: 257 insert_reused_count: 63 - query: EXPLAIN select dept.id, dept.name, project.name from emp, dept, project @@ -156,11 +156,11 @@ unnamed-2: SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q2.EMP_ID EQUALS _.ID AS q3 RETURN q2 } AS q2 RETURN (q1.ID AS ID, q1.NAME AS _1, q2.NAME AS _2) }' task_count: 15228 - task_total_time_ms: 862 + task_total_time_ms: 785 transform_count: 6857 - transform_time_ms: 194 + transform_time_ms: 205 transform_yield_count: 817 - insert_time_ms: 181 + insert_time_ms: 172 insert_new_count: 2151 insert_reused_count: 425 - query: EXPLAIN select * from ja join jb using(c1) join jd using(c1); @@ -169,11 +169,11 @@ unnamed-2: JA, EQUALS q1.C1]) AS q2 RETURN (q2 AS _0, q1 AS _1) } AS q3 RETURN (q3._0.C1 AS C1, q3._0.C2 AS C2, q3._1.C3 AS C3, q0.C4 AS C4) } task_count: 1195 - task_total_time_ms: 113 + task_total_time_ms: 155 transform_count: 508 - transform_time_ms: 29 + transform_time_ms: 67 transform_yield_count: 79 - insert_time_ms: 3 + insert_time_ms: 7 insert_new_count: 133 insert_reused_count: 21 - query: EXPLAIN select jua.c5, jub.c5, jud.c5 from jua join jub using(c1) join @@ -183,11 +183,11 @@ unnamed-2: JUA, EQUALS q1.C1]) AS q2 RETURN (q2 AS _0, q1 AS _1) } AS q3 RETURN (q3._0.C5 AS _0, q3._1.C5 AS _1, q0.C5 AS _2) } task_count: 1195 - task_total_time_ms: 170 + task_total_time_ms: 89 transform_count: 507 - transform_time_ms: 58 + transform_time_ms: 28 transform_yield_count: 79 - insert_time_ms: 7 + insert_time_ms: 4 insert_new_count: 133 insert_reused_count: 21 - query: EXPLAIN select * from jua join (select * from jub join jud using(c1)) as @@ -198,95 +198,168 @@ unnamed-2: q3 RETURN (q3._0.C1 AS C1, q3._0.C2 AS C2, q3._0.C5 AS _2, q3._1.C3 AS C3, q3._1.C5 AS _4, q0.C4 AS C4, q0.C5 AS _6) } task_count: 1497 - task_total_time_ms: 174 + task_total_time_ms: 139 transform_count: 595 transform_time_ms: 54 transform_yield_count: 97 - insert_time_ms: 10 + insert_time_ms: 4 insert_new_count: 184 insert_reused_count: 26 +- query: EXPLAIN select ja.c1, ja.c2, jb.c3 from ja inner join jb on true; + ref: join-tests.yamsql:425 + explain: SCAN([IS JA]) | FLATMAP q0 -> { SCAN([IS JB]) AS q1 RETURN (q0.C1 AS + C1, q0.C2 AS C2, q1.C3 AS C3) } + task_count: 460 + task_total_time_ms: 185 + transform_count: 151 + transform_time_ms: 136 + transform_yield_count: 38 + insert_time_ms: 3 + insert_new_count: 50 + insert_reused_count: 6 +- query: EXPLAIN select ja.c1, ja.c2, jb.c3 from ja, jb where true; + ref: join-tests.yamsql:431 + explain: SCAN([IS JA]) | FLATMAP q0 -> { SCAN([IS JB]) AS q1 RETURN (q0.C1 AS + C1, q0.C2 AS C2, q1.C3 AS C3) } + task_count: 460 + task_total_time_ms: 17 + transform_count: 151 + transform_time_ms: 7 + transform_yield_count: 38 + insert_time_ms: 0 + insert_new_count: 50 + insert_reused_count: 6 +- query: EXPLAIN select ja.c1, ja.c2, jb.c3 from ja inner join jb on false; + ref: join-tests.yamsql:437 + explain: SCAN([IS JA]) | FLATMAP q0 -> { SCAN([IS JB]) | FILTER false AS q1 RETURN + (q0.C1 AS C1, q0.C2 AS C2, q1.C3 AS C3) } + task_count: 466 + task_total_time_ms: 27 + transform_count: 149 + transform_time_ms: 12 + transform_yield_count: 38 + insert_time_ms: 0 + insert_new_count: 54 + insert_reused_count: 6 +- query: EXPLAIN select ja.c1, ja.c2, jb.c3 from ja, jb where false; + ref: join-tests.yamsql:443 + explain: SCAN([IS JA]) | FLATMAP q0 -> { SCAN([IS JB]) | FILTER false AS q1 RETURN + (q0.C1 AS C1, q0.C2 AS C2, q1.C3 AS C3) } + task_count: 466 + task_total_time_ms: 29 + transform_count: 149 + transform_time_ms: 11 + transform_yield_count: 38 + insert_time_ms: 0 + insert_new_count: 54 + insert_reused_count: 6 +- query: EXPLAIN select ja.c1, ja.c2, jb.c3 from ja inner join jb on cast(null as + boolean); + ref: join-tests.yamsql:449 + explain: SCAN([IS JB]) | FILTER CAST(NULL AS BOOLEAN) EQUALS true | FLATMAP q0 + -> { SCAN([IS JA]) AS q1 RETURN (q1.C1 AS C1, q1.C2 AS C2, q0.C3 AS C3) } + task_count: 447 + task_total_time_ms: 21 + transform_count: 143 + transform_time_ms: 8 + transform_yield_count: 36 + insert_time_ms: 0 + insert_new_count: 49 + insert_reused_count: 6 +- query: EXPLAIN select ja.c1, ja.c2, jb.c3 from ja, jb where cast(null as boolean); + ref: join-tests.yamsql:455 + explain: SCAN([IS JB]) | FILTER CAST(NULL AS BOOLEAN) EQUALS true | FLATMAP q0 + -> { SCAN([IS JA]) AS q1 RETURN (q1.C1 AS C1, q1.C2 AS C2, q0.C3 AS C3) } + task_count: 447 + task_total_time_ms: 49 + transform_count: 143 + transform_time_ms: 21 + transform_yield_count: 36 + insert_time_ms: 1 + insert_new_count: 49 + insert_reused_count: 6 three-way-joins-right-deep-planner: - query: EXPLAIN select fname, lname from emp inner join project on emp_id = emp.id inner join dept on dept_id = dept.id and dept.name = 'Sales'; - ref: join-tests.yamsql:433 + ref: join-tests.yamsql:479 explain: SCAN([IS DEPT]) | FILTER _.NAME EQUALS promote(@c29 AS STRING) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER q1.EMP_ID EQUALS _.ID AND _.DEPT_ID EQUALS q0.ID AS q2 RETURN q2 } AS q2 RETURN (q2.FNAME AS FNAME, q2.LNAME AS LNAME) } task_count: 1138 - task_total_time_ms: 73 + task_total_time_ms: 101 transform_count: 426 - transform_time_ms: 23 + transform_time_ms: 34 transform_yield_count: 77 - insert_time_ms: 2 + insert_time_ms: 4 insert_new_count: 133 insert_reused_count: 22 - query: EXPLAIN select dept.name, project.name from emp, dept, project where emp.dept_id = dept.id and project.emp_id = emp.id; - ref: join-tests.yamsql:438 + ref: join-tests.yamsql:484 explain: SCAN([IS PROJECT]) | FLATMAP q0 -> { SCAN([IS DEPT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q0.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.NAME AS _0, q0.NAME AS _1) } task_count: 1008 - task_total_time_ms: 79 + task_total_time_ms: 87 transform_count: 380 - transform_time_ms: 30 + transform_time_ms: 36 transform_yield_count: 69 - insert_time_ms: 2 + insert_time_ms: 4 insert_new_count: 114 insert_reused_count: 20 - query: EXPLAIN select dept.name, project.name from emp inner join dept on emp.dept_id = dept.id inner join project on project.emp_id = emp.id; - ref: join-tests.yamsql:445 + ref: join-tests.yamsql:491 explain: SCAN([IS PROJECT]) | FLATMAP q0 -> { SCAN([IS DEPT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q0.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.NAME AS _0, q0.NAME AS _1) } task_count: 1008 - task_total_time_ms: 104 + task_total_time_ms: 29 transform_count: 380 - transform_time_ms: 36 + transform_time_ms: 16 transform_yield_count: 69 - insert_time_ms: 3 + insert_time_ms: 1 insert_new_count: 114 insert_reused_count: 20 - query: EXPLAIN select * from (select dept.name, project.name from emp, dept, project where emp.dept_id = dept.id and project.emp_id = emp.id) X; - ref: join-tests.yamsql:452 + ref: join-tests.yamsql:498 explain: SCAN([IS PROJECT]) | FLATMAP q0 -> { SCAN([IS DEPT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q0.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.NAME AS _0, q0.NAME AS _1) } task_count: 1038 - task_total_time_ms: 84 + task_total_time_ms: 83 transform_count: 384 - transform_time_ms: 36 + transform_time_ms: 28 transform_yield_count: 71 insert_time_ms: 2 insert_new_count: 118 insert_reused_count: 20 - query: EXPLAIN select (*) from (select dept.name, project.name from emp, dept, project where emp.dept_id = dept.id and project.emp_id = emp.id) X; - ref: join-tests.yamsql:459 + ref: join-tests.yamsql:505 explain: SCAN([IS DEPT]) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q0.ID AND q1.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN ((q0.NAME AS _0, q1.NAME AS _1) AS _0) } task_count: 1038 - task_total_time_ms: 86 + task_total_time_ms: 59 transform_count: 384 - transform_time_ms: 28 + transform_time_ms: 15 transform_yield_count: 71 - insert_time_ms: 2 + insert_time_ms: 1 insert_new_count: 118 insert_reused_count: 20 - query: EXPLAIN select dept.name, project.name from project inner join emp on emp.id = project.emp_id inner join dept on emp.dept_id = dept.id; - ref: join-tests.yamsql:466 + ref: join-tests.yamsql:512 explain: SCAN([IS DEPT]) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP, EQUALS q1.EMP_ID]) | FILTER _.DEPT_ID EQUALS q0.ID AS q2 RETURN q1 } AS q1 RETURN (q0.NAME AS _0, q1.NAME AS _1) } task_count: 1041 - task_total_time_ms: 105 + task_total_time_ms: 90 transform_count: 381 - transform_time_ms: 28 + transform_time_ms: 33 transform_yield_count: 73 insert_time_ms: 3 insert_new_count: 123 @@ -294,31 +367,31 @@ three-way-joins-right-deep-planner: - query: EXPLAIN select dept.id, dept.name, project.name from emp, dept, project where emp.dept_id = dept.id and project.emp_id = emp.id and dept.id not in (1) - ref: join-tests.yamsql:473 + ref: join-tests.yamsql:519 explain: SCAN([IS DEPT]) | FILTER NOT _.ID IN promote(@c40 AS ARRAY(LONG)) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q0.ID AND q1.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q0.ID AS ID, q0.NAME AS _1, q1.NAME AS _2) } task_count: 1116 - task_total_time_ms: 75 + task_total_time_ms: 104 transform_count: 422 - transform_time_ms: 25 + transform_time_ms: 35 transform_yield_count: 75 - insert_time_ms: 2 + insert_time_ms: 3 insert_new_count: 127 insert_reused_count: 22 - query: EXPLAIN select dept.id, dept.name, project.name from emp inner join dept on emp.dept_id = dept.id and dept.id not in (1) inner join project on project.emp_id = emp.id - ref: join-tests.yamsql:479 + ref: join-tests.yamsql:525 explain: SCAN([IS DEPT]) | FILTER NOT _.ID IN promote(@c31 AS ARRAY(LONG)) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FLATMAP q1 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q0.ID AND q1.EMP_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q0.ID AS ID, q0.NAME AS _1, q1.NAME AS _2) } task_count: 1116 - task_total_time_ms: 86 + task_total_time_ms: 107 transform_count: 422 - transform_time_ms: 32 + transform_time_ms: 38 transform_yield_count: 75 insert_time_ms: 3 insert_new_count: 127 @@ -326,75 +399,75 @@ three-way-joins-right-deep-planner: - query: EXPLAIN select project.id, project.name from emp, dept, project where emp.dept_id = dept.id and project.emp_id = emp.id and dept.id not in (3) and project.id not in (3) - ref: join-tests.yamsql:485 + ref: join-tests.yamsql:531 explain: SCAN([IS EMP]) | FLATMAP q0 -> { SCAN([IS PROJECT]) | FILTER NOT _.ID IN promote(@c36 AS ARRAY(LONG)) AND _.EMP_ID EQUALS q0.ID | FLATMAP q1 -> { SCAN([IS DEPT]) | FILTER NOT _.ID IN promote(@c36 AS ARRAY(LONG)) AND q0.DEPT_ID EQUALS _.ID AS q2 RETURN q1 } AS q1 RETURN (q1.ID AS ID, q1.NAME AS NAME) } task_count: 1224 - task_total_time_ms: 96 + task_total_time_ms: 45 transform_count: 463 - transform_time_ms: 34 + transform_time_ms: 21 transform_yield_count: 81 - insert_time_ms: 3 + insert_time_ms: 2 insert_new_count: 140 insert_reused_count: 24 - query: EXPLAIN select dept.id, dept.name, project.name from emp, dept, project where emp.dept_id = dept.id and project.emp_id = emp.id and dept.id in (1, 2) - ref: join-tests.yamsql:490 + ref: join-tests.yamsql:536 explain: '[IN arrayDistinct(promote(@c39 AS ARRAY(LONG)))] | INJOIN q0 -> { SCAN([IS DEPT, EQUALS q0]) } | FLATMAP q1 -> { SCAN([IS PROJECT]) | FLATMAP q2 -> { SCAN([IS EMP]) | FILTER _.DEPT_ID EQUALS q1.ID AND q2.EMP_ID EQUALS _.ID AS q3 RETURN q2 } AS q2 RETURN (q1.ID AS ID, q1.NAME AS _1, q2.NAME AS _2) }' task_count: 4963 - task_total_time_ms: 377 + task_total_time_ms: 410 transform_count: 1903 - transform_time_ms: 100 + transform_time_ms: 118 transform_yield_count: 287 - insert_time_ms: 22 + insert_time_ms: 29 insert_new_count: 733 insert_reused_count: 102 - query: EXPLAIN select * from ja join jb using(c1) join jd using(c1); - ref: join-tests.yamsql:496 + ref: join-tests.yamsql:542 explain: SCAN([IS JD]) | FLATMAP q0 -> { SCAN([IS JB]) | FLATMAP q1 -> { SCAN([IS JA, EQUALS q1.C1]) AS q2 RETURN (q2 AS _0, q1 AS _1) } AS q3 RETURN (q3._0.C1 AS C1, q3._0.C2 AS C2, q3._1.C3 AS C3, q0.C4 AS C4) } task_count: 892 - task_total_time_ms: 110 + task_total_time_ms: 98 transform_count: 352 - transform_time_ms: 35 + transform_time_ms: 27 transform_yield_count: 64 insert_time_ms: 2 insert_new_count: 103 insert_reused_count: 12 - query: EXPLAIN select jua.c5, jub.c5, jud.c5 from jua join jub using(c1) join jud using(c1); - ref: join-tests.yamsql:501 + ref: join-tests.yamsql:547 explain: SCAN([IS JUD]) | FLATMAP q0 -> { SCAN([IS JUB]) | FLATMAP q1 -> { SCAN([IS JUA, EQUALS q1.C1]) AS q2 RETURN (q2 AS _0, q1 AS _1) } AS q3 RETURN (q3._0.C5 AS _0, q3._1.C5 AS _1, q0.C5 AS _2) } task_count: 892 - task_total_time_ms: 111 + task_total_time_ms: 65 transform_count: 351 - transform_time_ms: 39 + transform_time_ms: 21 transform_yield_count: 64 - insert_time_ms: 2 + insert_time_ms: 1 insert_new_count: 103 insert_reused_count: 12 - query: EXPLAIN select * from jua join (select * from jub join jud using(c1)) as X using (c1); - ref: join-tests.yamsql:506 + ref: join-tests.yamsql:552 explain: SCAN([IS JUD]) | FLATMAP q0 -> { SCAN([IS JUB, EQUALS q0.C1]) | FLATMAP q1 -> { SCAN([IS JUA, EQUALS q1.C1]) AS q2 RETURN (q2 AS _0, q1 AS _1) } AS q3 RETURN (q3._0.C1 AS C1, q3._0.C2 AS C2, q3._0.C5 AS _2, q3._1.C3 AS C3, q3._1.C5 AS _4, q0.C4 AS C4, q0.C5 AS _6) } task_count: 1094 - task_total_time_ms: 138 + task_total_time_ms: 112 transform_count: 387 - transform_time_ms: 43 + transform_time_ms: 39 transform_yield_count: 78 - insert_time_ms: 3 + insert_time_ms: 2 insert_new_count: 137 insert_reused_count: 13 diff --git a/yaml-tests/src/test/resources/join-tests.yamsql b/yaml-tests/src/test/resources/join-tests.yamsql index 8dbe88e7ff..386647bdc5 100644 --- a/yaml-tests/src/test/resources/join-tests.yamsql +++ b/yaml-tests/src/test/resources/join-tests.yamsql @@ -418,6 +418,54 @@ test_block: - query: select * from (select c11 as c1, c3 from (select c3 - 2 as c11, c3 from jub) as Z) as Y join (select c2 - 1 as c1, c5 from jua) as X using (c1); - supported_version: 4.10.4.0 - result: [{c1: 1, c3: 3, c5: 5}] + - + # inner join with ON TRUE: yields the cross product + - query: select ja.c1, ja.c2, jb.c3 from ja inner join jb on true; + - supported_version: !current_version + - explain: "SCAN([IS JA]) | FLATMAP q0 -> { SCAN([IS JB]) AS q1 RETURN (q0.C1 AS C1, q0.C2 AS C2, q1.C3 AS C3) }" + - result: [{c1: 1, c2: 2, c3: 3}] + - + # same cross product, but expressed using a comma-separated list and an explicit WHERE TRUE clause + - query: select ja.c1, ja.c2, jb.c3 from ja, jb where true; + - supported_version: !current_version + - explain: "SCAN([IS JA]) | FLATMAP q0 -> { SCAN([IS JB]) AS q1 RETURN (q0.C1 AS C1, q0.C2 AS C2, q1.C3 AS C3) }" + - result: [{c1: 1, c2: 2, c3: 3}] + - + # inner join with ON FALSE: yields an empty result + - query: select ja.c1, ja.c2, jb.c3 from ja inner join jb on false; + - supported_version: !current_version + - explain: "SCAN([IS JA]) | FLATMAP q0 -> { SCAN([IS JB]) | FILTER false AS q1 RETURN (q0.C1 AS C1, q0.C2 AS C2, q1.C3 AS C3) }" + - result: [] + - + # same join as above, but using an explicit WHERE FALSE clause + - query: select ja.c1, ja.c2, jb.c3 from ja, jb where false; + - supported_version: !current_version + - explain: "SCAN([IS JA]) | FLATMAP q0 -> { SCAN([IS JB]) | FILTER false AS q1 RETURN (q0.C1 AS C1, q0.C2 AS C2, q1.C3 AS C3) }" + - result: [] + - + # inner join with ON UNKNOWN: has the same effect as ON FALSE + - query: select ja.c1, ja.c2, jb.c3 from ja inner join jb on cast(null as boolean); + - supported_version: !current_version + - explain: "SCAN([IS JB]) | FILTER CAST(NULL AS BOOLEAN) EQUALS true | FLATMAP q0 -> { SCAN([IS JA]) AS q1 RETURN (q1.C1 AS C1, q1.C2 AS C2, q0.C3 AS C3) }" + - result: [] + - + # same join as above, but using an explicit WHERE NULL clause + - query: select ja.c1, ja.c2, jb.c3 from ja, jb where cast(null as boolean); + - supported_version: !current_version + - explain: "SCAN([IS JB]) | FILTER CAST(NULL AS BOOLEAN) EQUALS true | FLATMAP q0 -> { SCAN([IS JA]) AS q1 RETURN (q1.C1 AS C1, q1.C2 AS C2, q0.C3 AS C3) }" + - result: [] + - + # inner join with ON NULL: a plain NULL predicate is recognized as a null boolean and yields an empty result + - query: select ja.c1, ja.c2, jb.c3 from ja inner join jb on null; + - supported_version: !current_version + - explain: "SCAN([IS JA]) | FLATMAP q0 -> { SCAN([IS JB]) | FILTER null AS q1 RETURN (q0.C1 AS C1, q0.C2 AS C2, q1.C3 AS C3) }" + - result: [] + - + # same join as above, but using an explicit WHERE NULL clause + - query: select ja.c1, ja.c2, jb.c3 from ja, jb where null; + - supported_version: !current_version + - explain: "SCAN([IS JA]) | FLATMAP q0 -> { SCAN([IS JB]) | FILTER null AS q1 RETURN (q0.C1 AS C1, q0.C2 AS C2, q1.C3 AS C3) }" + - result: [] --- # All 3-way (or more) join queries from above, repeated with PLAN_RIGHT_DEEP enabled. test_block: