Implicit edge generation can create self-edge

XMLWordPrintableJSON

    • Type: Bug
    • Resolution: Duplicate
    • Priority: Major - P3
    • None
    • Affects Version/s: None
    • Component/s: None
    • Query Optimization
    • ALL
    • Hide
      /**
       * Reproduces a join optimizer tassert where implicit edge discovery infers an edge from a node to
       * itself after two local fields are equated to the same foreign field.
       *
       * @tags: [
       *   requires_fcv_90,
       *   requires_sbe,
       * ]
       */
      
      TestData.cleanUpCoreDumpsFromExpectedCrash = true;
      const conn = MongoRunner.runMongod({
          useLogFiles: false,
          setParameter: {
              featureFlagPathArrayness: true,
              internalEnableJoinOptimization: true,
              internalJoinReorderMode: "bottomUp",
          },
      });
      assert(conn);
      const db = conn.getDB(jsTestName());
      const base = db.base;
      const foreign = db.foreign;
      assert.commandWorked(base.insert({x: 1, z: 1}));
      assert.commandWorked(foreign.insert({y: 1}));
      assert.commandWorked(base.createIndexes([{x: 1}, {z: 1}]));
      assert.commandWorked(foreign.createIndex({y: 1}));
      
      // WILL FAIL: 11180001 "Self edges are not permitted"
      assert.commandWorked(
          db.runCommand({
              aggregate: base.getName(),
              pipeline: [
                  {
                      $lookup: {
                          from: foreign.getName(),
                          let: {lx: "$x", lz: "$z"},
                          pipeline: [
                              {
                                  $match: {
                                      $expr: {
                                          $and: [{$eq: ["$y", "$$lx"]}, {$eq: ["$y", "$$lz"]}],
                                      },
                                  },
                              },
                          ],
                          as: "joined",
                      },
                  },
                  {$unwind: "$joined"},
              ],
              cursor: {},
          }),
      );
      
      MongoRunner.stopMongod(conn, null, {allowedExitCode: MongoRunner.EXIT_ABORT});
       
      Show
      /**  * Reproduces a join optimizer tassert where implicit edge discovery infers an edge from a node to  * itself after two local fields are equated to the same foreign field.  *  * @tags: [  *   requires_fcv_90,  *   requires_sbe,  * ]  */ TestData.cleanUpCoreDumpsFromExpectedCrash = true ; const conn = MongoRunner.runMongod({     useLogFiles: false ,     setParameter: {         featureFlagPathArrayness: true ,         internalEnableJoinOptimization: true ,         internalJoinReorderMode: "bottomUp" ,     }, }); assert (conn); const db = conn.getDB(jsTestName()); const base = db.base; const foreign = db.foreign; assert .commandWorked(base.insert({x: 1, z: 1})); assert .commandWorked(foreign.insert({y: 1})); assert .commandWorked(base.createIndexes([{x: 1}, {z: 1}])); assert .commandWorked(foreign.createIndex({y: 1})); // WILL FAIL: 11180001 "Self edges are not permitted" assert .commandWorked(     db.runCommand({         aggregate: base.getName(),         pipeline: [             {                 $lookup: {                     from: foreign.getName(),                     let: {lx: "$x" , lz: "$z" },                     pipeline: [                         {                             $match: {                                 $expr: {                                     $and: [{$eq: [ "$y" , "$$lx" ]}, {$eq: [ "$y" , "$$lz" ]}],                                 },                             },                         },                     ],                     as: "joined" ,                 },             },             {$unwind: "$joined" },         ],         cursor: {},     }), ); MongoRunner.stopMongod(conn, null , {allowedExitCode: MongoRunner.EXIT_ABORT});
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      Implicit-edge generation can create a self-edge, tripping 11180001addImplicitEdges() unions equal path ids, then blindly adds equality edges between every pair in a DS component. If one lookup has two join predicates equating the same foreign path to two different local paths, the component contains two paths from the same node. MutableJoinGraph::addEdge() then rejects the implied same-node edge.

            Assignee:
            Max Verbinnen
            Reporter:
            Max Verbinnen
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: