diff --git a/hugegraph-cassandra/src/main/java/com/baidu/hugegraph/backend/store/cassandra/CassandraStoreProvider.java b/hugegraph-cassandra/src/main/java/com/baidu/hugegraph/backend/store/cassandra/CassandraStoreProvider.java index 402f7ab642..1b7087720b 100644 --- a/hugegraph-cassandra/src/main/java/com/baidu/hugegraph/backend/store/cassandra/CassandraStoreProvider.java +++ b/hugegraph-cassandra/src/main/java/com/baidu/hugegraph/backend/store/cassandra/CassandraStoreProvider.java @@ -52,7 +52,8 @@ public String version() { * [1.0] HugeGraph-1328: supports backend table version checking * [1.1] HugeGraph-1322: add support for full-text search * [1.2] #296: support range sortKey feature + * [1.3] #455: fix scylladb backend doesn't support label query in page */ - return "1.2"; + return "1.3"; } } diff --git a/hugegraph-cassandra/src/main/java/com/baidu/hugegraph/backend/store/cassandra/CassandraTables.java b/hugegraph-cassandra/src/main/java/com/baidu/hugegraph/backend/store/cassandra/CassandraTables.java index e3b1c9f443..c2acc12f8b 100644 --- a/hugegraph-cassandra/src/main/java/com/baidu/hugegraph/backend/store/cassandra/CassandraTables.java +++ b/hugegraph-cassandra/src/main/java/com/baidu/hugegraph/backend/store/cassandra/CassandraTables.java @@ -213,16 +213,16 @@ public void init(CassandraSessionPool.Session session) { ImmutableMap pkeys = ImmutableMap.of( HugeKeys.ID, DATATYPE_IL ); - ImmutableMap ckeys = ImmutableMap.of( - HugeKeys.BASE_TYPE, DataType.tinyint(), - HugeKeys.BASE_VALUE, DATATYPE_SL - ); - ImmutableMap columns = ImmutableMap.of( - HugeKeys.NAME, DataType.text(), - HugeKeys.INDEX_TYPE, DataType.tinyint(), - HugeKeys.FIELDS, DataType.list(DATATYPE_PK), - HugeKeys.STATUS, DataType.tinyint() - ); + ImmutableMap ckeys = ImmutableMap.of(); + ImmutableMap columns = ImmutableMap + .builder() + .put(HugeKeys.NAME, DataType.text()) + .put(HugeKeys.BASE_TYPE, DataType.tinyint()) + .put(HugeKeys.BASE_VALUE, DATATYPE_SL) + .put(HugeKeys.INDEX_TYPE, DataType.tinyint()) + .put(HugeKeys.FIELDS, DataType.list(DATATYPE_PK)) + .put(HugeKeys.STATUS, DataType.tinyint()) + .build(); this.createTable(session, pkeys, ckeys, columns); this.createIndex(session, NAME_INDEX, HugeKeys.NAME); @@ -297,6 +297,10 @@ protected Directions direction() { return this.direction; } + protected String labelIndexTable() { + return this.table(); + } + @Override public void init(CassandraSessionPool.Session session) { ImmutableMap pkeys = ImmutableMap.of( @@ -397,7 +401,7 @@ protected void deleteEdgesByLabel(CassandraSessionPool.Session session, final String OTHER_VERTEX = formatKey(HugeKeys.OTHER_VERTEX); // Query edges by label index - Select select = QueryBuilder.select().from(this.table()); + Select select = QueryBuilder.select().from(this.labelIndexTable()); select.where(formatEQ(HugeKeys.LABEL, label.asLong())); ResultSet rs; @@ -421,7 +425,7 @@ protected void deleteEdgesByLabel(CassandraSessionPool.Session session, session.add(buildDelete(label, otherVertex, Directions.IN)); count += 2; - if (count > COMMIT_DELETE_BATCH - 2) { + if (count >= COMMIT_DELETE_BATCH - 2) { session.commit(); count = 0; } diff --git a/hugegraph-core/src/main/java/com/baidu/hugegraph/backend/tx/SchemaTransaction.java b/hugegraph-core/src/main/java/com/baidu/hugegraph/backend/tx/SchemaTransaction.java index 6faae6fc7e..45411ed677 100644 --- a/hugegraph-core/src/main/java/com/baidu/hugegraph/backend/tx/SchemaTransaction.java +++ b/hugegraph-core/src/main/java/com/baidu/hugegraph/backend/tx/SchemaTransaction.java @@ -121,6 +121,7 @@ public PropertyKey getPropertyKey(Id id) { @Watched(prefix = "schema") public PropertyKey getPropertyKey(String name) { E.checkArgumentNotNull(name, "Property key name can't be null"); + E.checkArgument(!name.isEmpty(), "Property key name can't be empty"); return this.getSchema(HugeType.PROPERTY_KEY, name); } @@ -170,6 +171,7 @@ public VertexLabel getVertexLabel(Id id) { @Watched(prefix = "schema") public VertexLabel getVertexLabel(String name) { E.checkArgumentNotNull(name, "Vertex label name can't be null"); + E.checkArgument(!name.isEmpty(), "Vertex label name can't be empty"); return this.getSchema(HugeType.VERTEX_LABEL, name); } @@ -194,6 +196,7 @@ public EdgeLabel getEdgeLabel(Id id) { @Watched(prefix = "schema") public EdgeLabel getEdgeLabel(String name) { E.checkArgumentNotNull(name, "Edge label name can't be null"); + E.checkArgument(!name.isEmpty(), "Edge label name can't be empty"); return this.getSchema(HugeType.EDGE_LABEL, name); } @@ -225,6 +228,7 @@ public IndexLabel getIndexLabel(Id id) { @Watched(prefix = "schema") public IndexLabel getIndexLabel(String name) { E.checkArgumentNotNull(name, "Index label name can't be null"); + E.checkArgument(!name.isEmpty(), "Index label name can't be empty"); return this.getSchema(HugeType.INDEX_LABEL, name); } diff --git a/hugegraph-scylladb/src/main/java/com/baidu/hugegraph/backend/store/scylladb/ScyllaDBStoreProvider.java b/hugegraph-scylladb/src/main/java/com/baidu/hugegraph/backend/store/scylladb/ScyllaDBStoreProvider.java index e5ee097db4..0aca4393e2 100644 --- a/hugegraph-scylladb/src/main/java/com/baidu/hugegraph/backend/store/scylladb/ScyllaDBStoreProvider.java +++ b/hugegraph-scylladb/src/main/java/com/baidu/hugegraph/backend/store/scylladb/ScyllaDBStoreProvider.java @@ -34,6 +34,9 @@ public class ScyllaDBStoreProvider extends CassandraStoreProvider { private static final Logger LOG = Log.logger(CassandraStore.class); + // TODO: read ScyllaDB version from conf + private static final int VERSION = 20; + private static final BackendFeatures FEATURES = new ScyllaDBFeatures(); @Override @@ -80,14 +83,25 @@ public ScyllaDBSchemaStore(BackendStoreProvider provider, String keyspace, String store) { super(provider, keyspace, store); - registerTableManager(HugeType.VERTEX_LABEL, - new ScyllaDBTables.VertexLabel()); - registerTableManager(HugeType.EDGE_LABEL, - new ScyllaDBTables.EdgeLabel()); - registerTableManager(HugeType.PROPERTY_KEY, - new ScyllaDBTables.PropertyKey()); - registerTableManager(HugeType.INDEX_LABEL, - new ScyllaDBTables.IndexLabel()); + if (VERSION >= 20) { + registerTableManager(HugeType.VERTEX_LABEL, + new ScyllaDBTablesWithMV.VertexLabel()); + registerTableManager(HugeType.EDGE_LABEL, + new ScyllaDBTablesWithMV.EdgeLabel()); + registerTableManager(HugeType.PROPERTY_KEY, + new ScyllaDBTablesWithMV.PropertyKey()); + registerTableManager(HugeType.INDEX_LABEL, + new ScyllaDBTablesWithMV.IndexLabel()); + } else { + registerTableManager(HugeType.VERTEX_LABEL, + new ScyllaDBTables.VertexLabel()); + registerTableManager(HugeType.EDGE_LABEL, + new ScyllaDBTables.EdgeLabel()); + registerTableManager(HugeType.PROPERTY_KEY, + new ScyllaDBTables.PropertyKey()); + registerTableManager(HugeType.INDEX_LABEL, + new ScyllaDBTables.IndexLabel()); + } } @Override @@ -103,10 +117,7 @@ public ScyllaDBGraphStore(BackendStoreProvider provider, String keyspace, String store) { super(provider, keyspace, store); - // TODO: read Scylla version from conf - int version = 17; - - if (version >= 20) { + if (VERSION >= 20) { registerTableManager(HugeType.VERTEX, new ScyllaDBTablesWithMV.Vertex(store)); registerTableManager(HugeType.EDGE_OUT, diff --git a/hugegraph-scylladb/src/main/java/com/baidu/hugegraph/backend/store/scylladb/ScyllaDBTablesWithMV.java b/hugegraph-scylladb/src/main/java/com/baidu/hugegraph/backend/store/scylladb/ScyllaDBTablesWithMV.java index a0371d6697..96a2db6a89 100644 --- a/hugegraph-scylladb/src/main/java/com/baidu/hugegraph/backend/store/scylladb/ScyllaDBTablesWithMV.java +++ b/hugegraph-scylladb/src/main/java/com/baidu/hugegraph/backend/store/scylladb/ScyllaDBTablesWithMV.java @@ -23,7 +23,6 @@ import java.util.Set; import java.util.stream.Collectors; -import com.baidu.hugegraph.backend.id.Id; import com.baidu.hugegraph.backend.query.Condition; import com.baidu.hugegraph.backend.query.ConditionQuery; import com.baidu.hugegraph.backend.query.Query; @@ -36,24 +35,167 @@ public class ScyllaDBTablesWithMV { - protected static boolean isQueryByLabel(Query query) { + private static boolean isQueryBySpecifiedKey(Query query, HugeKeys key) { Set conditions = query.conditions(); if (query instanceof ConditionQuery && !conditions.isEmpty()) { ConditionQuery cq = (ConditionQuery) query; - Id label = (Id) cq.condition(HugeKeys.LABEL); - if (label != null && cq.allSysprop() && - conditions.size() == 1 && - cq.containsCondition(HugeKeys.LABEL, - Condition.RelationType.EQ)) { - return true; - } + Object value = cq.condition(key); + return value != null && cq.allSysprop() && + conditions.size() == 1 && + cq.containsCondition(key, Condition.RelationType.EQ); } return false; } + private static boolean isQueryByLabel(Query query) { + return isQueryBySpecifiedKey(query, HugeKeys.LABEL); + } + + private static boolean isQueryByName(Query query) { + return isQueryBySpecifiedKey(query, HugeKeys.NAME); + } + + private static String mvNameTable(String table) { + return "mv_name2" + table; + } + + private static String mvLabelTable(String table) { + return "mv_label2" + table; + } + + private static void createSchemaIndexTable( + CassandraSessionPool.Session session, + String mvName, String table) { + final String NAME = CassandraTable.formatKey(HugeKeys.NAME); + final String ID = CassandraTable.formatKey(HugeKeys.ID); + String cql = String.format( + "CREATE MATERIALIZED VIEW IF NOT EXISTS %s AS " + + " SELECT * FROM %s " + + " WHERE %s IS NOT NULL " + + " PRIMARY KEY(%s, %s)", + mvName, table, NAME, + NAME, ID); + session.execute(cql); + } + + private static void dropIndexTable(CassandraSessionPool.Session session, + String mvName) { + String cql = String.format("DROP MATERIALIZED VIEW IF EXISTS %s", + mvName); + session.execute(cql); + } + + public static class PropertyKey extends CassandraTables.PropertyKey { + + private final String MV_NAME2PK = mvNameTable(this.table()); + + @Override + protected void createIndex(CassandraSessionPool.Session session, + String indexLabel, + HugeKeys column) { + createSchemaIndexTable(session, MV_NAME2PK, this.table()); + } + + @Override + protected void dropTable(CassandraSessionPool.Session session) { + dropIndexTable(session, MV_NAME2PK); + super.dropTable(session); + } + + @Override + protected List query2Select(String table, Query query) { + if (isQueryByName(query)) { + // Query from materialized view + return super.query2Select(MV_NAME2VL, query); + } + return super.query2Select(table, query); + } + } + + public static class EdgeLabel extends CassandraTables.EdgeLabel { + + private final String MV_NAME2EL = mvNameTable(this.table()); + + @Override + protected void createIndex(CassandraSessionPool.Session session, + String indexLabel, + HugeKeys column) { + createSchemaIndexTable(session, MV_NAME2EL, this.table()); + } + + @Override + protected void dropTable(CassandraSessionPool.Session session) { + dropIndexTable(session, MV_NAME2EL); + super.dropTable(session); + } + + @Override + protected List query2Select(String table, Query query) { + if (isQueryByName(query)) { + // Query from materialized view + return super.query2Select(MV_NAME2IL, query); + } + return super.query2Select(table, query); + } + } + public static class Vertex extends CassandraTables.Vertex { - private static final String MV_LABEL2VERTEX = "mv_label2vertex"; + private final String MV_LABEL2VERTEX = mvLabelTable(this.table()); public Vertex(String store) { super(store); @@ -70,23 +212,16 @@ protected void createIndex(CassandraSessionPool.Session session, " SELECT * FROM %s " + " WHERE %s IS NOT NULL " + " PRIMARY KEY(%s, %s)", - MV_LABEL2VERTEX, this.table(), LABEL, - LABEL, ID); + MV_LABEL2VERTEX, this.table(), LABEL, LABEL, ID); session.execute(cql); } @Override protected void dropTable(CassandraSessionPool.Session session) { - this.dropIndexTable(session); + dropIndexTable(session, MV_LABEL2VERTEX); super.dropTable(session); } - private void dropIndexTable(CassandraSessionPool.Session session) { - String cql = String.format( - "DROP MATERIALIZED VIEW IF EXISTS %s", - MV_LABEL2VERTEX); - session.execute(cql); - } /** * Query data from label index table if just want to query by label @@ -103,7 +238,7 @@ protected List query2Select(String table, Query query) { return super.query2Select(table, query); } + @Override + protected String labelIndexTable() { + return MV_LABEL2EDGE; + } + public static Edge out(String store) { return new Edge(store, Directions.OUT); }