diff --git a/src/main/java/com/arangodb/entity/ArangoDBVersion.java b/src/main/java/com/arangodb/entity/ArangoDBVersion.java index 265c46c47..6eceef582 100644 --- a/src/main/java/com/arangodb/entity/ArangoDBVersion.java +++ b/src/main/java/com/arangodb/entity/ArangoDBVersion.java @@ -28,10 +28,6 @@ */ public class ArangoDBVersion implements Entity { - public enum License { - ENTERPRISE, COMMUNITY - } - private String server; private String version; private License license; diff --git a/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java b/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java index 6476db78b..cecff4aa9 100644 --- a/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java +++ b/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java @@ -39,6 +39,9 @@ public class CollectionPropertiesEntity extends CollectionEntity { private Collection shardKeys; private final ReplicationFactor replicationFactor; + private String shardingStrategy; // cluster option + private String smartJoinAttribute; // enterprise option + public CollectionPropertiesEntity() { super(); replicationFactor = new ReplicationFactor(); @@ -126,4 +129,20 @@ public void setSatellite(final Boolean satellite) { this.replicationFactor.setSatellite(satellite); } + public String getShardingStrategy() { + return shardingStrategy; + } + + public void setShardingStrategy(String shardingStrategy) { + this.shardingStrategy = shardingStrategy; + } + + public String getSmartJoinAttribute() { + return smartJoinAttribute; + } + + public void setSmartJoinAttribute(String smartJoinAttribute) { + this.smartJoinAttribute = smartJoinAttribute; + } + } diff --git a/src/main/java/com/arangodb/entity/License.java b/src/main/java/com/arangodb/entity/License.java new file mode 100644 index 000000000..0b9b8e789 --- /dev/null +++ b/src/main/java/com/arangodb/entity/License.java @@ -0,0 +1,30 @@ +/* + * DISCLAIMER + * + * Copyright 2019 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +/** + * @author Axel Becker + */ +public enum License { + + ENTERPRISE, COMMUNITY + +} diff --git a/src/main/java/com/arangodb/entity/ShardingStrategy.java b/src/main/java/com/arangodb/entity/ShardingStrategy.java new file mode 100644 index 000000000..5252ec065 --- /dev/null +++ b/src/main/java/com/arangodb/entity/ShardingStrategy.java @@ -0,0 +1,45 @@ +/* + * DISCLAIMER + * + * Copyright 2019 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +/** + * @author Axel Becker + * https://www.arangodb.com/docs/3.4/http/collection-creating.html + */ +public enum ShardingStrategy { + + COMMUNITY_COMPAT("community-compat"), + ENTERPRISE_COMPAT("enterprise-compat"), + ENTERPRISE_SMART_EDGE_COMPAT("enterprise-smart-edge-compat"), + HASH("hash"), + ENTERPRISE_HASH_SMART_EDGE("enterprise-hash-smart-edge"); + + private String internalName; + + private ShardingStrategy(String internalName) { + this.internalName = internalName; + } + + public String getInternalName() { + return this.internalName; + } + +} diff --git a/src/main/java/com/arangodb/internal/ArangoExecutorSync.java b/src/main/java/com/arangodb/internal/ArangoExecutorSync.java index 82a57fab9..9436ab047 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecutorSync.java +++ b/src/main/java/com/arangodb/internal/ArangoExecutorSync.java @@ -53,13 +53,13 @@ public T execute(final Request request, final Type type, final HostHandle ho return execute(request, new ResponseDeserializer() { @Override public T deserialize(final Response response) throws VPackException { - return createResult(type, response); + T result = createResult(type, response); + return result; } }, hostHandle); } - public T execute(final Request request, final ResponseDeserializer responseDeserializer) - throws ArangoDBException { + public T execute(final Request request, final ResponseDeserializer responseDeserializer) throws ArangoDBException { return execute(request, responseDeserializer, null); } @@ -67,9 +67,14 @@ public T execute( final Request request, final ResponseDeserializer responseDeserializer, final HostHandle hostHandle) throws ArangoDBException { + try { + final Response response = protocol.execute(request, hostHandle); - return responseDeserializer.deserialize(response); + T deserialize = responseDeserializer.deserialize(response); + + return deserialize; + } catch (final VPackException e) { throw new ArangoDBException(e); } diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index 73a8a39c6..bc3be8a37 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -117,8 +117,13 @@ protected Request getVersionRequest() { } protected Request createCollectionRequest(final String name, final CollectionCreateOptions options) { - return request(name(), RequestType.POST, InternalArangoCollection.PATH_API_COLLECTION).setBody( - util().serialize(OptionsBuilder.build(options != null ? options : new CollectionCreateOptions(), name))); + + VPackSlice body = util().serialize(OptionsBuilder.build(options != null ? options : new CollectionCreateOptions(), name)); + + return request( + name(), + RequestType.POST, + InternalArangoCollection.PATH_API_COLLECTION).setBody(body); } protected Request getCollectionsRequest(final CollectionsReadOptions options) { diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java b/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java index a5a96a92d..f7d0e13ad 100644 --- a/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java +++ b/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java @@ -31,11 +31,11 @@ import org.slf4j.LoggerFactory; import com.arangodb.entity.ArangoDBVersion; -import com.arangodb.entity.ArangoDBVersion.License; import com.arangodb.entity.BaseDocument; import com.arangodb.entity.BaseEdgeDocument; import com.arangodb.entity.CollectionStatus; import com.arangodb.entity.CollectionType; +import com.arangodb.entity.License; import com.arangodb.entity.LogLevel; import com.arangodb.entity.Permissions; import com.arangodb.entity.QueryExecutionState; @@ -45,8 +45,8 @@ import com.arangodb.entity.arangosearch.ArangoSearchProperties; import com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity; import com.arangodb.entity.arangosearch.CollectionLink; -import com.arangodb.entity.arangosearch.ConsolidationType; import com.arangodb.entity.arangosearch.ConsolidationPolicy; +import com.arangodb.entity.arangosearch.ConsolidationType; import com.arangodb.entity.arangosearch.FieldLink; import com.arangodb.entity.arangosearch.StoreValuesType; import com.arangodb.velocypack.VPackDeserializationContext; @@ -153,12 +153,13 @@ public LogLevel deserialize( } }; - public static final VPackDeserializer LICENSE = new VPackDeserializer() { + public static final VPackDeserializer LICENSE = new VPackDeserializer() { @Override public License deserialize( final VPackSlice parent, final VPackSlice vpack, final VPackDeserializationContext context) throws VPackException { + return License.valueOf(vpack.getAsString().toUpperCase()); } }; diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java b/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java index 2199a8f6e..7ec963f74 100644 --- a/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java +++ b/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java @@ -23,12 +23,12 @@ import java.lang.reflect.Field; import java.util.Date; -import com.arangodb.entity.ArangoDBVersion; import com.arangodb.entity.BaseDocument; import com.arangodb.entity.BaseEdgeDocument; import com.arangodb.entity.CollectionStatus; import com.arangodb.entity.CollectionType; import com.arangodb.entity.DocumentField; +import com.arangodb.entity.License; import com.arangodb.entity.LogLevel; import com.arangodb.entity.Permissions; import com.arangodb.entity.QueryEntity; @@ -37,8 +37,8 @@ import com.arangodb.entity.ViewType; import com.arangodb.entity.arangosearch.ArangoSearchProperties; import com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity; -import com.arangodb.entity.arangosearch.ConsolidationType; import com.arangodb.entity.arangosearch.ConsolidationPolicy; +import com.arangodb.entity.arangosearch.ConsolidationType; import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.model.TraversalOptions; import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions; @@ -78,8 +78,7 @@ public String translateName(final Field field) { context.registerSerializer(Permissions.class, VPackSerializers.PERMISSIONS); context.registerSerializer(ReplicationFactor.class, VPackSerializers.REPLICATION_FACTOR); context.registerSerializer(ViewType.class, VPackSerializers.VIEW_TYPE); - context.registerSerializer(ArangoSearchPropertiesOptions.class, - VPackSerializers.ARANGO_SEARCH_PROPERTIES_OPTIONS); + context.registerSerializer(ArangoSearchPropertiesOptions.class, VPackSerializers.ARANGO_SEARCH_PROPERTIES_OPTIONS); context.registerSerializer(ArangoSearchProperties.class, VPackSerializers.ARANGO_SEARCH_PROPERTIES); context.registerSerializer(ConsolidationType.class, VPackSerializers.CONSOLIDATE_TYPE); @@ -90,14 +89,13 @@ public String translateName(final Field field) { context.registerDeserializer(BaseEdgeDocument.class, VPackDeserializers.BASE_EDGE_DOCUMENT); context.registerDeserializer(QueryEntity.PROPERTY_STARTED, Date.class, VPackDeserializers.DATE_STRING); context.registerDeserializer(LogLevel.class, VPackDeserializers.LOG_LEVEL); - context.registerDeserializer(ArangoDBVersion.License.class, VPackDeserializers.LICENSE); + context.registerDeserializer(License.class, VPackDeserializers.LICENSE); context.registerDeserializer(Permissions.class, VPackDeserializers.PERMISSIONS); context.registerDeserializer(QueryExecutionState.class, VPackDeserializers.QUERY_EXECUTION_STATE); context.registerDeserializer(ReplicationFactor.class, VPackDeserializers.REPLICATION_FACTOR); context.registerDeserializer(ViewType.class, VPackDeserializers.VIEW_TYPE); context.registerDeserializer(ArangoSearchProperties.class, VPackDeserializers.ARANGO_SEARCH_PROPERTIES); - context.registerDeserializer(ArangoSearchPropertiesEntity.class, - VPackDeserializers.ARANGO_SEARCH_PROPERTIES_ENTITY); + context.registerDeserializer(ArangoSearchPropertiesEntity.class, VPackDeserializers.ARANGO_SEARCH_PROPERTIES_ENTITY); context.registerDeserializer(ConsolidationPolicy.class, VPackDeserializers.CONSOLIDATE); } diff --git a/src/main/java/com/arangodb/model/CollectionCreateOptions.java b/src/main/java/com/arangodb/model/CollectionCreateOptions.java index 79d691e50..4984efb47 100644 --- a/src/main/java/com/arangodb/model/CollectionCreateOptions.java +++ b/src/main/java/com/arangodb/model/CollectionCreateOptions.java @@ -46,6 +46,9 @@ public class CollectionCreateOptions { private CollectionType type; private Integer indexBuckets; private String distributeShardsLike; + + private String shardingStrategy; // cluster option + private String smartJoinAttribute; // enterprise option public CollectionCreateOptions() { super(); @@ -209,10 +212,32 @@ public CollectionCreateOptions shardKeys(final String... shardKeys) { return this; } - public Integer getNumberOfShards() { - return numberOfShards; + /** + * @param smartJoinAttribute + * @return options + */ + public CollectionCreateOptions smartJoinAttribute(final String smartJoinAttribute) { + this.smartJoinAttribute = smartJoinAttribute; + return this; + } + + public String getSmartJoinAttribute() { + return smartJoinAttribute; } + /** + * @param shardingStrategy + * @return options + */ + public CollectionCreateOptions shardingStrategy(final String shardingStrategy) { + this.shardingStrategy = shardingStrategy; + return this; + } + + public String getShardingStrategy() { + return shardingStrategy; + } + /** * @param numberOfShards * (The default is 1): in a cluster, this value determines the number of shards to create for the @@ -223,7 +248,11 @@ public CollectionCreateOptions numberOfShards(final Integer numberOfShards) { this.numberOfShards = numberOfShards; return this; } - + + public Integer getNumberOfShards() { + return numberOfShards; + } + public Boolean getIsSystem() { return isSystem; } diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/src/test/java/com/arangodb/ArangoDatabaseTest.java index e7c76450e..7f8070981 100644 --- a/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -44,6 +44,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.arangodb.ArangoDB.Builder; import com.arangodb.entity.AqlExecutionExplainEntity; @@ -51,7 +53,6 @@ import com.arangodb.entity.AqlFunctionEntity; import com.arangodb.entity.AqlParseEntity; import com.arangodb.entity.ArangoDBVersion; -import com.arangodb.entity.ArangoDBVersion.License; import com.arangodb.entity.BaseDocument; import com.arangodb.entity.BaseEdgeDocument; import com.arangodb.entity.CollectionEntity; @@ -62,6 +63,7 @@ import com.arangodb.entity.EdgeDefinition; import com.arangodb.entity.GraphEntity; import com.arangodb.entity.IndexEntity; +import com.arangodb.entity.License; import com.arangodb.entity.PathEntity; import com.arangodb.entity.Permissions; import com.arangodb.entity.QueryCachePropertiesEntity; @@ -70,6 +72,7 @@ import com.arangodb.entity.QueryExecutionState; import com.arangodb.entity.QueryTrackingPropertiesEntity; import com.arangodb.entity.ServerRole; +import com.arangodb.entity.ShardingStrategy; import com.arangodb.entity.TraversalEntity; import com.arangodb.model.AqlFunctionDeleteOptions; import com.arangodb.model.AqlQueryOptions; @@ -91,6 +94,8 @@ */ @RunWith(Parameterized.class) public class ArangoDatabaseTest extends BaseTest { + + Logger LOG = LoggerFactory.getLogger(ArangoDatabaseTest.class); private static final String COLLECTION_NAME = "db_test"; private static final String GRAPH_NAME = "graph_test"; @@ -184,25 +189,75 @@ public void createSatelliteCollection() { @Test public void createCollectionWithNumberOfShards() { + if (arangoDB.getRole() == ServerRole.SINGLE) { return; } + try { - final CollectionEntity result = db.createCollection(COLLECTION_NAME, - new CollectionCreateOptions().numberOfShards(2)); + + final CollectionEntity result = db.createCollection(COLLECTION_NAME, new CollectionCreateOptions().numberOfShards(2)); + assertThat(result, is(notNullValue())); assertThat(result.getId(), is(notNullValue())); assertThat(db.collection(COLLECTION_NAME).getProperties().getNumberOfShards(), is(2)); + + } finally { + db.collection(COLLECTION_NAME).drop(); + } + } + + @Test + public void createCollectionWithShardingStrategys() { + + if (arangoDB.getRole() == ServerRole.SINGLE) { + LOG.info("Skip Test on SINGLE SERVER"); + return; + } + + try { + + final CollectionEntity result = db.createCollection(COLLECTION_NAME, new CollectionCreateOptions().shardingStrategy(ShardingStrategy.COMMUNITY_COMPAT.getInternalName())); + + assertThat(result, is(notNullValue())); + assertThat(result.getId(), is(notNullValue())); + assertThat(db.collection(COLLECTION_NAME).getProperties().getShardingStrategy(), is(ShardingStrategy.COMMUNITY_COMPAT.getInternalName())); + + } finally { + db.collection(COLLECTION_NAME).drop(); + } + } + + @Test + public void createCollectionWithSmartJoinAttribute() { + + if (arangoDB.getVersion().getLicense() == License.COMMUNITY) { + LOG.info("Skip Test on COMMUNITY SERVER"); + return; + } + + try { + + final CollectionEntity result = db.createCollection(COLLECTION_NAME, new CollectionCreateOptions().smartJoinAttribute("test123")); + + assertThat(result, is(notNullValue())); + assertThat(result.getId(), is(notNullValue())); + assertThat(db.collection(COLLECTION_NAME).getProperties().getSmartJoinAttribute(), is("test123")); + } finally { db.collection(COLLECTION_NAME).drop(); } } + @Test public void createCollectionWithNumberOfShardsAndShardKey() { + if (arangoDB.getRole() == ServerRole.SINGLE) { + LOG.info("Skip Test on SINGLE SERVER"); return; } + try { final CollectionEntity result = db.createCollection(COLLECTION_NAME, new CollectionCreateOptions().numberOfShards(2).shardKeys("a")); @@ -218,9 +273,12 @@ public void createCollectionWithNumberOfShardsAndShardKey() { @Test public void createCollectionWithNumberOfShardsAndShardKeys() { + if (arangoDB.getRole() == ServerRole.SINGLE) { + LOG.info("Skip Test on SINGLE SERVER"); return; } + try { final CollectionEntity result = db.createCollection(COLLECTION_NAME, new CollectionCreateOptions().numberOfShards(2).shardKeys("a", "b")); @@ -236,14 +294,19 @@ public void createCollectionWithNumberOfShardsAndShardKeys() { @Test public void createCollectionWithDistributeShardsLike() { + if (arangoDB.getVersion().getLicense() == License.ENTERPRISE && arangoDB.getRole() != ServerRole.SINGLE) { + + final Integer numberOfShards = 3; + db.createCollection(COLLECTION_NAME, new CollectionCreateOptions().numberOfShards(numberOfShards)); - db.createCollection(COLLECTION_NAME + "2", - new CollectionCreateOptions().distributeShardsLike(COLLECTION_NAME)); + db.createCollection(COLLECTION_NAME + "2", new CollectionCreateOptions().distributeShardsLike(COLLECTION_NAME)); + assertThat(db.collection(COLLECTION_NAME).getProperties().getNumberOfShards(), is(numberOfShards)); assertThat(db.collection(COLLECTION_NAME + "2").getProperties().getNumberOfShards(), is(numberOfShards)); } + } @Test @@ -259,9 +322,11 @@ public void deleteCollection() { @Test public void deleteSystemCollection() { + if (arangoDB.getRole() != ServerRole.SINGLE) { return; } + final String name = "_system_test"; db.createCollection(name, new CollectionCreateOptions().isSystem(true)); db.collection(name).drop(true); diff --git a/src/test/java/com/arangodb/ArangoGraphTest.java b/src/test/java/com/arangodb/ArangoGraphTest.java index d480f8f37..7dae53608 100644 --- a/src/test/java/com/arangodb/ArangoGraphTest.java +++ b/src/test/java/com/arangodb/ArangoGraphTest.java @@ -38,10 +38,10 @@ import org.junit.runners.Parameterized; import com.arangodb.ArangoDB.Builder; -import com.arangodb.entity.ArangoDBVersion.License; import com.arangodb.entity.CollectionPropertiesEntity; import com.arangodb.entity.EdgeDefinition; import com.arangodb.entity.GraphEntity; +import com.arangodb.entity.License; import com.arangodb.entity.ServerRole; import com.arangodb.model.GraphCreateOptions; @@ -232,24 +232,28 @@ public void removeEdgeDefinition() { @Test public void smartGraph() { + if (arangoDB.getVersion().getLicense() == License.ENTERPRISE) { - for (final String collection : new String[] { EDGE_COL_1, EDGE_COL_2, VERTEX_COL_1, VERTEX_COL_2, - VERTEX_COL_3, VERTEX_COL_4 }) { + + for (final String collection : new String[] { EDGE_COL_1, EDGE_COL_2, VERTEX_COL_1, VERTEX_COL_2, VERTEX_COL_3, VERTEX_COL_4 }) { try { db.collection(collection).drop(); } catch (final ArangoDBException e) { + } } try { db.graph(GRAPH_NAME).drop(); } catch (final ArangoDBException e) { } + final Collection edgeDefinitions = new ArrayList(); + edgeDefinitions.add(new EdgeDefinition().collection(EDGE_COL_1).from(VERTEX_COL_1).to(VERTEX_COL_2)); - edgeDefinitions - .add(new EdgeDefinition().collection(EDGE_COL_2).from(VERTEX_COL_2).to(VERTEX_COL_1, VERTEX_COL_3)); - final GraphEntity graph = db.createGraph(GRAPH_NAME, edgeDefinitions, - new GraphCreateOptions().isSmart(true).smartGraphAttribute("test").numberOfShards(2)); + edgeDefinitions.add(new EdgeDefinition().collection(EDGE_COL_2).from(VERTEX_COL_2).to(VERTEX_COL_1, VERTEX_COL_3)); + + final GraphEntity graph = db.createGraph(GRAPH_NAME, edgeDefinitions, new GraphCreateOptions().isSmart(true).smartGraphAttribute("test").numberOfShards(2)); + assertThat(graph, is(notNullValue())); assertThat(graph.getIsSmart(), is(true)); assertThat(graph.getSmartGraphAttribute(), is("test"));