cockroachdb / cockroach

CockroachDB — the cloud native, distributed SQL database designed for high availability, effortless scale, and control over data placement.
https://www.cockroachlabs.com
Other
30.19k stars 3.82k forks source link

roachtest: internal error: output cols mismatch #136250

Open yuzefovich opened 3 days ago

yuzefovich commented 3 days ago

Extracted from here. On crdb_test binaries we get

ERROR: internal error: output cols mismatch: (118-143,146-149) vs (118-128,130-143,146-149)
SQLSTATE: XX000
DETAIL: stack trace:
pkg/sql/opt/props/verify.go:82: VerifyAgainst()
pkg/sql/opt/memo/check_expr.go:52: CheckExpr()
bazel-out/darwin_arm64-fastbuild/bin/pkg/sql/opt/memo/expr.og.go:26322: AddLookupJoinToGroup()
pkg/sql/opt/xform/join_funcs.go:514: func1()
pkg/sql/opt/xform/scan_index_iter.go:299: ForEachStartingAfter()
pkg/sql/opt/xform/scan_index_iter.go:202: ForEach()
pkg/sql/opt/xform/join_funcs.go:411: generateLookupJoinsImpl()
pkg/sql/opt/xform/join_funcs.go:259: GenerateLookupJoins()
...
CREATE TABLE table_1 (
  col1_0 BOOL,
  col1_1 REFCURSOR,
  col1_2 PG_LSN,
  col1_3 BOX2D,
  col1_4 INT8,
  col1_5 STRING,
  col1_6 STRING,
  col1_7 INT8,
  col1_8 STRING AS (lower(NULL)) VIRTUAL,
  col1_9 STRING,
  PRIMARY KEY (col1_8),
  INDEX (lower(CAST(col1_3 AS STRING)), lower(CAST(col1_2 AS STRING)) DESC) STORING(col1_2)
);

SET testing_optimizer_random_seed = 4882365012661120111;

SET testing_optimizer_disable_rule_probability = 0.500000;

SELECT NULL
  FROM table_1 AS tab_879
  JOIN table_1 AS tab_880 ON true
       FULL JOIN table_1 AS tab_881 JOIN table_1 ON true JOIN table_1 AS tab_883 ON true ON true
 WHERE (
        NOT (
              EXISTS(
                  SELECT NULL
                    FROM table_1 AS tab_884 JOIN table_1 ON true
                ORDER BY tab_884.crdb_internal_origin_timestamp DESC NULLS FIRST,
                         tab_884.col1_4 ASC NULLS LAST,
                         tab_884.col1_0 ASC NULLS LAST,
                         tab_884.col1_2 ASC NULLS LAST
              )
            )
       )
    OR (
        (
          tab_881.col1_0
          AND 0
            NOT IN (
                SELECT NULL
                  FROM table_1 AS tab_886
                  JOIN table_1 AS tab_887 ON tab_886.col1_5 = tab_887.col1_5
                                         AND tab_886.col1_0 = tab_887.col1_0
              )
        )
        OR (tab_883.col1_0 AND tab_879.col1_0)
       );

Jira issue: CRDB-44942

DrewKimball commented 3 days ago

Here's an optimizer test repro:

exec-ddl
CREATE TABLE table_1 (
  col1_0 BOOL,
  col1_1 REFCURSOR,
  col1_2 PG_LSN,
  col1_3 BOX2D,
  col1_4 INT8,
  col1_5 STRING,
  col1_6 STRING,
  col1_7 INT8,
  col1_8 STRING AS (lower(NULL)) VIRTUAL,
  col1_9 STRING,
  foo_col DECIMAL,
  PRIMARY KEY (col1_8),
  INDEX (CAST(col1_3 AS STRING), CAST(col1_2 AS STRING))
);
----

opt disable=(MergeProjects,PruneProjectCols)
SELECT NULL
  FROM table_1 AS tab_879
  JOIN table_1 AS tab_880 ON true
  FULL JOIN table_1 AS tab_881 ON true
  JOIN table_1 ON true
  JOIN table_1 AS tab_883 ON true
 WHERE NOT EXISTS (SELECT NULL FROM table_1 AS tab_884 JOIN table_1 ON true)
    OR NOT EXISTS (SELECT NULL FROM table_1 AS tab_886 JOIN table_1 AS tab_887 ON tab_886.col1_5 = tab_887.col1_5);
----

There's a bug in InlineProjectProject, where we're mutating a Project operator's Passthrough set rather than copying it:

--- a/pkg/sql/opt/norm/inline_funcs.go
+++ b/pkg/sql/opt/norm/inline_funcs.go
@@ -245,7 +245,7 @@ func (c *CustomFuncs) InlineProjectProject(
        }

        // Add any outer passthrough columns that refer to inner synthesized columns.
-       newPassthrough := passthrough
+       newPassthrough := passthrough.Copy()
        if !newPassthrough.Empty() {
                for i := range innerProjections {
                        item := &innerProjections[i]

The large number of columns and joins in the test is necessary to spill the removed columns into the large set, which is shared between passthrough and newPassthrough without the fix.