Skip to content

Commit 4324966

Browse files
committed
feat: update studio supporting new HASH INDEX
Issue #3527
1 parent f1983bf commit 4324966

3 files changed

Lines changed: 86 additions & 4 deletions

File tree

engine/src/main/java/com/arcadedb/query/sql/parser/CreateIndexStatement.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ public void validate() throws CommandSQLParsingException {
7272
}
7373
case "GEOSPATIAL" -> {
7474
}
75+
case "UNIQUE_HASH" -> {
76+
}
77+
case "NOTUNIQUE_HASH" -> {
78+
}
7579
default -> throw new CommandSQLParsingException("Index type '" + typeAsString + "' is not supported");
7680
}
7781
}
@@ -110,6 +114,12 @@ else if (typeAsString.equalsIgnoreCase("UNIQUE")) {
110114
} else if (typeAsString.equalsIgnoreCase("GEOSPATIAL")) {
111115
indexType = Schema.INDEX_TYPE.GEOSPATIAL;
112116
unique = false;
117+
} else if (typeAsString.equalsIgnoreCase("UNIQUE_HASH")) {
118+
indexType = Schema.INDEX_TYPE.HASH;
119+
unique = true;
120+
} else if (typeAsString.equalsIgnoreCase("NOTUNIQUE_HASH")) {
121+
indexType = Schema.INDEX_TYPE.HASH;
122+
unique = false;
113123
} else
114124
throw new CommandSQLParsingException("Index type '" + typeAsString + "' is not supported");
115125

engine/src/test/java/com/arcadedb/index/HashIndexTest.java

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,71 @@ void transactionRollback() {
385385
});
386386
}
387387

388+
@Test
389+
void sqlCreateUniqueHash() {
390+
database.command("sql", "CREATE DOCUMENT TYPE SqlHashDoc");
391+
database.command("sql", "CREATE PROPERTY SqlHashDoc.code INTEGER");
392+
database.command("sql", "CREATE INDEX ON SqlHashDoc (code) UNIQUE_HASH");
393+
394+
database.transaction(() -> {
395+
for (int i = 0; i < 100; ++i) {
396+
final MutableDocument doc = database.newDocument("SqlHashDoc");
397+
doc.set("code", i);
398+
doc.save();
399+
}
400+
});
401+
402+
database.transaction(() -> {
403+
final Index index = database.getSchema().getIndexByName("SqlHashDoc[code]");
404+
assertThat(index.getType()).isEqualTo(Schema.INDEX_TYPE.HASH);
405+
assertThat(index.isUnique()).isTrue();
406+
407+
for (int i = 0; i < 100; ++i) {
408+
final IndexCursor cursor = index.get(new Object[] { i });
409+
assertThat(cursor.hasNext()).isTrue();
410+
}
411+
});
412+
413+
// Duplicate rejection
414+
assertThatThrownBy(() -> database.transaction(() -> {
415+
final MutableDocument doc = database.newDocument("SqlHashDoc");
416+
doc.set("code", 0);
417+
doc.save();
418+
})).isInstanceOf(DuplicatedKeyException.class);
419+
}
420+
421+
@Test
422+
void sqlCreateNotUniqueHash() {
423+
database.command("sql", "CREATE DOCUMENT TYPE SqlHashNUDoc");
424+
database.command("sql", "CREATE PROPERTY SqlHashNUDoc.tag STRING");
425+
database.command("sql", "CREATE INDEX ON SqlHashNUDoc (tag) NOTUNIQUE_HASH");
426+
427+
database.transaction(() -> {
428+
for (int i = 0; i < 50; ++i) {
429+
final MutableDocument doc = database.newDocument("SqlHashNUDoc");
430+
doc.set("tag", "group_" + (i % 5));
431+
doc.save();
432+
}
433+
});
434+
435+
database.transaction(() -> {
436+
final Index index = database.getSchema().getIndexByName("SqlHashNUDoc[tag]");
437+
assertThat(index.getType()).isEqualTo(Schema.INDEX_TYPE.HASH);
438+
assertThat(index.isUnique()).isFalse();
439+
440+
// Each group should have 10 entries
441+
for (int g = 0; g < 5; ++g) {
442+
final IndexCursor cursor = index.get(new Object[] { "group_" + g });
443+
int count = 0;
444+
while (cursor.hasNext()) {
445+
cursor.next();
446+
count++;
447+
}
448+
assertThat(count).isEqualTo(10);
449+
}
450+
});
451+
}
452+
388453
@Override
389454
protected void beginTest() {
390455
database.transaction(() -> {

studio/src/main/resources/static/js/studio-database.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -815,7 +815,8 @@ function createIndex(typeName) {
815815

816816
html += "<label for='inputCreateIdxAlgorithm'>Index Algorithm <span style='color:#dc3545'>*</span></label>";
817817
html += "<select class='form-select mt-1 mb-3' id='inputCreateIdxAlgorithm'>";
818-
html += "<option value='LSM_TREE' selected>LSM_TREE — default</option>";
818+
html += "<option value='LSM_TREE' selected>LSM_TREE — default, supports range queries</option>";
819+
html += "<option value='HASH'>HASH — O(1) equality lookups, no range queries</option>";
819820
html += "<option value='FULL_TEXT'>FULL_TEXT — full-text search index</option>";
820821
html += "<option value='LSM_VECTOR'>LSM_VECTOR — vector/embedding similarity index</option>";
821822
html += "</select>";
@@ -873,14 +874,20 @@ function createIndex(typeName) {
873874
let nullStrategy = $("#inputCreateIdxNullStrategy").val();
874875
let ifNotExists = $("#inputCreateIdxIfNotExists").prop("checked");
875876

876-
let indexTypeSql = algorithm == "LSM_TREE" ? (unique ? "UNIQUE" : "NOTUNIQUE") : algorithm;
877+
let indexTypeSql;
878+
if (algorithm == "LSM_TREE")
879+
indexTypeSql = unique ? "UNIQUE" : "NOTUNIQUE";
880+
else if (algorithm == "HASH")
881+
indexTypeSql = unique ? "UNIQUE_HASH" : "NOTUNIQUE_HASH";
882+
else
883+
indexTypeSql = algorithm;
877884

878885
let command = "CREATE INDEX";
879886
if (ifNotExists) command += " IF NOT EXISTS";
880887
command += " ON `" + typeName + "` (";
881888
command += selectedProps.map(function (p) { return "`" + p + "`"; }).join(", ");
882889
command += ") " + indexTypeSql;
883-
if (algorithm == "LSM_TREE" && nullStrategy != "") command += " NULL_STRATEGY " + nullStrategy;
890+
if ((algorithm == "LSM_TREE" || algorithm == "HASH") && nullStrategy != "") command += " NULL_STRATEGY " + nullStrategy;
884891

885892
jQuery.ajax({
886893
type: "POST",
@@ -905,7 +912,7 @@ function createIndex(typeName) {
905912
} else {
906913
$("#createIdxPropsNormal").show();
907914
$("#createIdxPropsVector").hide();
908-
$("#createIdxLsmOptions").toggle(alg == "LSM_TREE");
915+
$("#createIdxLsmOptions").toggle(alg == "LSM_TREE" || alg == "HASH");
909916
}
910917
}
911918
$("#inputCreateIdxAlgorithm").on("change", updateIdxVisibility);

0 commit comments

Comments
 (0)