Visitar URL original
Schema: after #10348, DROP TYPE and ALTER TYPE ... BUCKET - fail after an indexed supertype rename, and the refused statement still changes the schema · Issue #10412 · ArcadeData/arcadedb · GitHub
Skip to content

Schema: after #10348, DROP TYPE and ALTER TYPE ... BUCKET - fail after an indexed supertype rename, and the refused statement still changes the schema #10412

Closed

Description

@tae898

After #10348 (merge ea180479d7), three schema sequences that worked on main before it (d21784c4d8) and on 26.10.2 now end in a refused statement that still changes the schema. All three rename an indexed supertype (#10348 changed how a rename relabels the sub-indexes of an inherited index); the refusal names the type's old name, or the index as not valid. In case 3 the schema in memory and the schema after a reopen also differ: the refused DROP TYPE removed T64 in memory, T64 comes back after the reopen, and the index T66[p] is gone. Found by the schema fuzz I ran to verify #10348 (SchemaOps.java, seeds 1-30), shrunk to these statements.

1. DROP TYPE of a subtype after its indexed supertype was renamed.

CREATE DOCUMENT TYPE T22 BUCKETS 3
CREATE DOCUMENT TYPE T25 EXTENDS T22
CREATE PROPERTY T22.p STRING
CREATE INDEX ON T22 (p) NOTUNIQUE
ALTER TYPE T22 NAME T28
DROP TYPE T25
  • on the merge: REFUSED SchemaException: Cannot drop the index 'T25_0_N' (error=com.arcadedb.exception.SchemaException: Type with name 'T22' was not found), and yet the schema changed. Afterwards: T25{super [], buckets [], indexes []} T28{super [], buckets [T28_0, T28_1, T28_2], indexes [T28[p]]}; after a reopen: T25{super [], buckets [], indexes []} T28{super [], buckets [T28_0, T28_1, T28_2], indexes [T28[p]]}
  • on d21784c4d8 and on 26.10.2: the statement succeeds; after a reopen: T28{super [], buckets [T28_0, T28_1, T28_2], indexes [T28[p]]}

2. ALTER TYPE ... BUCKET - on a renamed subtype after its indexed supertype was renamed.

CREATE EDGE TYPE T1
CREATE EDGE TYPE T2 EXTENDS T1
ALTER TYPE T2 NAME T4
CREATE PROPERTY T1.p STRING
CREATE INDEX ON T1 (p) NOTUNIQUE
ALTER TYPE T1 NAME T10
ALTER TYPE T4 BUCKET -T4_0
  • on the merge: REFUSED SchemaException: Cannot drop the index 'T4_0_N' (error=com.arcadedb.exception.SchemaException: Type with name 'T1' was not found), and yet the schema changed. Afterwards: T10{super [], buckets [T10_0], indexes [T10[p]]} T4{super [T10], buckets [], indexes []}; after a reopen: T10{super [], buckets [T10_0], indexes [T10[p]]} T4{super [T10], buckets [], indexes []}
  • on d21784c4d8 and on 26.10.2: the statement succeeds; after a reopen: T10{super [], buckets [T10_0], indexes [T10[p]]} T4{super [T10], buckets [], indexes []}

3. An indexed type renamed twice loses its last bucket, then DROP TYPE of its subtype.

CREATE DOCUMENT TYPE T1
ALTER TYPE T1 NAME T13
CREATE DOCUMENT TYPE T15 EXTENDS T13
CREATE PROPERTY T15.p STRING
CREATE INDEX ON T15 (p) NOTUNIQUE
CREATE DOCUMENT TYPE T64 EXTENDS T15 BUCKETS 4
ALTER TYPE T15 NAME T65
ALTER TYPE T65 NAME T66
ALTER TYPE T66 BUCKET -T66_0
DROP TYPE T64
  • on the merge: REFUSED IndexException: Index 'T66[p]' is not valid. Probably has been drop or rebuilt, and yet the schema changed. Afterwards: T13{super [], buckets [T13_0], indexes []} T66{super [T13], buckets [], indexes [T66[p]]}; after a reopen: T13{super [], buckets [T13_0], indexes []} T64{super [T66], buckets [], indexes []} T66{super [T13], buckets [], indexes []}
  • on d21784c4d8 and on 26.10.2: the statement succeeds; after a reopen: T13{super [], buckets [T13_0], indexes []} T66{super [T13], buckets [], indexes []}

Embedded, eclipse-temurin 25 (-XX:+UseCompactObjectHeaders) and 21, identical on both; CI-built jars of each commit; each case on a fresh database. Generated index names are shortened to _N.

RenameIndex.java
// REMOVE WHEN: the rename-and-index schema findings on ea180479d7 (#10348's merge, 2026-10-20) are filed and verified on their fix.
// java RenameIndex.java DBDIR: three cases, each on a fresh database. Every statement's outcome, then the schema (types, supertypes,
// buckets, indexes), then a close (which writes the schema) and the schema after a reopen.
import com.arcadedb.database.*;
import com.arcadedb.schema.*;
import java.util.*;

public class RenameIndex {
  static final String[][] CASES = {
    { "1: DROP TYPE of a subtype after its indexed supertype was renamed",
      "CREATE DOCUMENT TYPE T22 BUCKETS 3", "CREATE DOCUMENT TYPE T25 EXTENDS T22", "CREATE PROPERTY T22.p STRING", "CREATE INDEX ON T22 (p) NOTUNIQUE",
      "ALTER TYPE T22 NAME T28", "DROP TYPE T25" },
    { "2: ALTER TYPE ... BUCKET - on a renamed subtype after its indexed supertype was renamed",
      "CREATE EDGE TYPE T1", "CREATE EDGE TYPE T2 EXTENDS T1", "ALTER TYPE T2 NAME T4", "CREATE PROPERTY T1.p STRING", "CREATE INDEX ON T1 (p) NOTUNIQUE",
      "ALTER TYPE T1 NAME T10", "ALTER TYPE T4 BUCKET -T4_0" },
    { "3: an indexed type renamed twice loses its last bucket, then DROP TYPE of its subtype",
      "CREATE DOCUMENT TYPE T1", "ALTER TYPE T1 NAME T13", "CREATE DOCUMENT TYPE T15 EXTENDS T13", "CREATE PROPERTY T15.p STRING", "CREATE INDEX ON T15 (p) NOTUNIQUE",
      "CREATE DOCUMENT TYPE T64 EXTENDS T15 BUCKETS 4", "ALTER TYPE T15 NAME T65", "ALTER TYPE T65 NAME T66", "ALTER TYPE T66 BUCKET -T66_0", "DROP TYPE T64" } };
  public static void main(String[] a) throws Exception {
    System.out.println("RESULT engine " + com.arcadedb.Constants.getRawVersion() + " " + com.arcadedb.Constants.getBuildNumber());
    int c = 0;
    for (String[] cs : CASES) {
      System.out.println("RESULT === case " + cs[0]);
      DatabaseFactory f = new DatabaseFactory(a[0] + "/c" + (c++)); if (f.exists()) f.open().drop(); Database db = f.create();
      for (int i = 1; i < cs.length; i++) {
        String before = schema(db), r;
        try { db.command("sql", cs[i]).close(); r = "ok"; } catch (Exception e) { r = "REFUSED " + e.getClass().getSimpleName() + ": " + e.getMessage(); }
        String after = schema(db);
        System.out.println("RESULT " + cs[i] + " -> " + r + (r.startsWith("REFUSED") && !before.equals(after) ? " | SCHEMA CHANGED ANYWAY" : ""));
      }
      System.out.println("RESULT   schema: " + schema(db));
      try { db.close(); System.out.println("RESULT   close: ok"); } catch (Exception e) { System.out.println("RESULT   close: " + e.getClass().getSimpleName() + ": " + e.getMessage()); }
      try { Database d2 = f.open(); System.out.println("RESULT   after reopen: " + schema(d2)); d2.close(); }
      catch (Exception e) { System.out.println("RESULT   reopen: " + e.getClass().getSimpleName() + ": " + e.getMessage()); }
    }
    System.exit(0);
  }
  static String schema(Database db) {
    StringBuilder b = new StringBuilder(); List<DocumentType> ts = new ArrayList<>(db.getSchema().getTypes()); ts.sort(Comparator.comparing(DocumentType::getName));
    for (DocumentType t : ts) {
      List<String> sup = new ArrayList<>(); for (DocumentType s : t.getSuperTypes()) sup.add(s.getName());
      List<String> bk = new ArrayList<>(); for (var x : t.getBuckets(false)) bk.add(x.getName());
      List<String> ix = new ArrayList<>(); try { for (var x : t.getAllIndexes(false)) ix.add(x.getName()); } catch (Exception e) { ix.add("EXC " + e.getMessage()); }
      b.append(t.getName()).append("{super ").append(sup).append(", buckets ").append(bk).append(", indexes ").append(ix).append("} ");
    }
    return b.toString().trim();
  }
}

Activity

  1. added
    engineCore engine: document/schema API
    severity:majorA feature is broken or returns wrong results, with no practical workaround
    on Oct 19, 2026
  2. added
    in progressThe team is actively working on this issue
    on Oct 19, 2026
  3. self-assigned this
    on Oct 19, 2026
  4. added this to the 26.11.1 milestone on Oct 19, 2026
  5. added a commit that references this issue on Oct 20, 2026
  6. lvca commented on Oct 20, 2026

    @lvca
    Member

    Fixed in #10422, released in 26.11.1.

    Cause: an index created with CREATE INDEX on a type that already had sub types kept the index of each sub type's bucket labelled with the super type until the next reopen. After renaming the super type, DROP TYPE and ALTER TYPE ... BUCKET - on the sub type could not find it. Dropping the last sub type of an indexed type that had lost its own buckets could also leave an empty index behind.

    Now the index of each bucket names the type that owns the bucket as soon as it is created, so your three sequences complete and the schema is the same before and after a reopen.

    A refused schema statement that still keeps part of its changes is a separate problem, tracked in #10421.


    ❤️ 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.

  7. removed
    in progressThe team is actively working on this issue
    on Oct 20, 2026
  8. added a commit that references this issue on Nov 5, 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 APIseverity:majorA feature is broken or returns wrong results, with no practical workaroundsql

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions