Visitar URL original
openCypher: a pattern predicate over an edge type that the Graph Analytical View does not list is answered from the view, so NOT (a)-[:F]->(b) excludes nothing and (a)-[:F]->(b) matches nothing (count(*) only) · Issue #9377 · ArcadeData/arcadedb · GitHub
Skip to content

openCypher: a pattern predicate over an edge type that the Graph Analytical View does not list is answered from the view, so NOT (a)-[:F]->(b) excludes nothing and (a)-[:F]->(b) matches nothing (count(*) only) #9377

Closed
humemai/arcadedb-embedded-python
#257

Description

@tae898

A Graph Analytical View that lists the edge types of the chain but not an edge type named by a pattern predicate is used for a count(*), and the predicate is then evaluated against the view, where the unlisted edge type has no edges.
WHERE NOT (a)-[:F]->(b) removes nothing and WHERE (a)-[:F]->(b) keeps nothing, although the F edges exist.
The same predicates answer correctly with no view, with a view that lists F, behind a WITH, and in a query that returns rows instead of count(*).
Found while verifying #9354 with a randomized differential; it is older than that PR and reproduces on the official 26.10.1 jars.

Reproduction

Engine API only: vertices x, y, z of type V, edges x -E-> y, x -F-> y, y -E-> z.
The view covers every vertex type and the edge type E but not F.

import com.arcadedb.database.Database;
import com.arcadedb.database.DatabaseFactory;
import com.arcadedb.database.RID;
import com.arcadedb.query.sql.executor.ResultSet;

public class ViewEdgeCoverage {
  public static void main(final String[] args) throws Exception {
    System.out.println("engine " + com.arcadedb.Constants.getRawVersion() + " build " + com.arcadedb.Constants.getBuildNumber() + ", java " + System.getProperty("java.version"));
    final DatabaseFactory f = new DatabaseFactory(args[0]);
    if (f.exists())
      f.open().drop();
    final Database db = f.create();
    db.command("sql", "CREATE VERTEX TYPE V");
    db.command("sql", "CREATE EDGE TYPE E");
    db.command("sql", "CREATE EDGE TYPE F");
    db.transaction(() -> {
      final RID x = db.newVertex("V").save().getIdentity(), y = db.newVertex("V").save().getIdentity(), z = db.newVertex("V").save().getIdentity();
      x.asVertex().newEdge("E", y).save();
      x.asVertex().newEdge("F", y).save();
      y.asVertex().newEdge("E", z).save();
    });
    // { text, expected }
    final String[][] qs = {
        { "MATCH (a:V)-[:E]->(b:V) WHERE NOT (a)-[:F]->(b) RETURN count(*) AS n", "1" },
        { "MATCH (a:V)-[:E]->(b:V) WHERE (a)-[:F]->(b) RETURN count(*) AS n", "1" },
        { "MATCH (a:V)-[:E]->(b:V)-[:E]->(c:V) WHERE NOT (a)-[:F]->(b) RETURN count(*) AS n", "0" },
        { "MATCH (a:V)-[:E]->(b:V) WITH a, b WHERE NOT (a)-[:F]->(b) RETURN count(*) AS n", "1" } };
    for (final String edgeTypes : new String[] { "none", "E", "E, F" }) {
      if (!edgeTypes.equals("none")) {
        db.command("sql", "DROP GRAPH ANALYTICAL VIEW IF EXISTS gav");
        db.command("sql", "CREATE GRAPH ANALYTICAL VIEW gav VERTEX TYPES (V) EDGE TYPES (" + edgeTypes + ") UPDATE MODE OFF");
        for (int i = 0; i < 6000; i++) {
          try (ResultSet rs = db.query("sql", "SELECT FROM schema:graphAnalyticalViews WHERE name = ?", "gav")) {
            if (rs.hasNext() && "READY".equals(rs.next().getProperty("status")))
              break;
          }
          Thread.sleep(20);
        }
      }
      for (final String[] q : qs)
        try (ResultSet rs = db.query("opencypher", q[0])) {
          System.out.println("view over edge types (" + edgeTypes + ") | " + q[0] + " -> " + rs.next().getProperty("n") + " (expected " + q[1] + ")");
        }
    }
    db.close();
  }
}

Run with java --add-modules=jdk.incubator.vector --enable-native-access=ALL-UNNAMED -cp "<arcadedb lib>/*" ViewEdgeCoverage.java <empty directory>.

Output

The lines for the view over E only, identical on Temurin 25.0.4+7 (with -XX:+UseCompactObjectHeaders) and Temurin 21.0.12+8, on the official 26.10.1 jars (build d36b4ca3ae4c170abc73598e0dffa2bb58e06621) and on main 246821a605a4202c69f0426e7d753cf8b89025ce (26.11.1-SNAPSHOT), apart from the third line (0, which is right, on 26.10.1, and 1 on main):

view over edge types (E) | MATCH (a:V)-[:E]->(b:V) WHERE NOT (a)-[:F]->(b) RETURN count(*) AS n -> 2 (expected 1)
view over edge types (E) | MATCH (a:V)-[:E]->(b:V) WHERE (a)-[:F]->(b) RETURN count(*) AS n -> 0 (expected 1)
view over edge types (E) | MATCH (a:V)-[:E]->(b:V)-[:E]->(c:V) WHERE NOT (a)-[:F]->(b) RETURN count(*) AS n -> 1 (expected 0)
view over edge types (E) | MATCH (a:V)-[:E]->(b:V) WITH a, b WHERE NOT (a)-[:F]->(b) RETURN count(*) AS n -> 1 (expected 1)

The no-view and E, F lines of the same run all equal the expected column (1, 1, 0, 1).
The expected counts are the row pipeline's: the pair (x, y) has an F edge, so it is excluded by the NOT form and is the only match of the plain form.

The edge types that a pattern predicate or a negated pattern names are not part of what decides whether a view may serve the query, only the edge types of the chain hops seem to be (the same selection by edge type that #9301 describes for vertex types).

Activity

  1. added
    in progressThe team is actively working on this issue
    on Oct 6, 2026
  2. self-assigned this
    on Oct 6, 2026
  3. added this to the 26.11.1 milestone on Oct 6, 2026
  4. added a commit that references this issue on Oct 7, 2026
  5. lvca commented on Oct 7, 2026

    @lvca
    Member

    Confirmed and fixed in #9383 (26.11.1). A Graph Analytical View answered pattern predicates such as NOT (a)-[:F]->(b) for edge types it does not list, where it holds no edges. Those lookups now read the record instead, so results are the same with and without the view.


    ❤️ Thanks for helping make ArcadeDB better! ArcadeDB is free and open source, sustained by its community. If it's useful to you or your company, please consider becoming a sponsor to keep development going.

  6. removed
    in progressThe team is actively working on this issue
    on Oct 7, 2026
  7. added a commit that references this issue on Oct 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugengineCore engine: document/schema APIopencypherseverity:minorCosmetic, documentation, edge case, or a workaround exists

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions