Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion database_graphs.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ type CreateGraphOptions struct {
// IsDisjoint set isDisjoint flag for Graph. Required ArangoDB 3.7+
IsDisjoint bool
// Satellites contains an array of collection names that will be used to create SatelliteCollections for a Hybrid (Disjoint) SmartGraph (Enterprise Edition only)
Satellites []string `json:"satellites"`
Satellites []string `json:"satellites,omitempty"`
}

// EdgeDefinition contains all information needed to define a single edge in a graph.
Expand Down
26 changes: 9 additions & 17 deletions database_graphs_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,11 +167,12 @@ type createGraphAdditionalOptions struct {
// IsDisjoint set isDisjoint flag for Graph. Required ArangoDB 3.7+
IsDisjoint bool `json:"isDisjoint,omitempty"`
// Satellites contains an array of collection names that will be used to create SatelliteCollections for a Hybrid (Disjoint) SmartGraph (Enterprise Edition only)
Satellites []string `json:"satellites"`
Satellites []string `json:"satellites,omitempty"`
}

// CreateGraph creates a new graph with given name and options, and opens a connection to it.
// If a graph with given name already exists within the database, a DuplicateError is returned.
// todo test
func (d *database) CreateGraph(ctx context.Context, name string, options *CreateGraphOptions) (Graph, error) {
input := createGraphOptions{
Name: name,
Expand All @@ -180,22 +181,13 @@ func (d *database) CreateGraph(ctx context.Context, name string, options *Create
input.OrphanVertexCollections = options.OrphanVertexCollections
input.EdgeDefinitions = options.EdgeDefinitions
input.IsSmart = options.IsSmart
if options.ReplicationFactor == SatelliteGraph {
input.Options = &createGraphAdditionalOptions{
SmartGraphAttribute: options.SmartGraphAttribute,
ReplicationFactor: graphReplicationFactor(options.ReplicationFactor),
IsDisjoint: options.IsDisjoint,
Satellites: options.Satellites,
}
} else if options.SmartGraphAttribute != "" || options.NumberOfShards != 0 {
input.Options = &createGraphAdditionalOptions{
SmartGraphAttribute: options.SmartGraphAttribute,
NumberOfShards: options.NumberOfShards,
ReplicationFactor: graphReplicationFactor(options.ReplicationFactor),
WriteConcern: options.WriteConcern,
IsDisjoint: options.IsDisjoint,
Satellites: options.Satellites,
}
input.Options = &createGraphAdditionalOptions{
SmartGraphAttribute: options.SmartGraphAttribute,
NumberOfShards: options.NumberOfShards,
ReplicationFactor: graphReplicationFactor(options.ReplicationFactor),
WriteConcern: options.WriteConcern,
IsDisjoint: options.IsDisjoint,
Satellites: options.Satellites,
}
}
req, err := d.conn.NewRequest("POST", path.Join(d.relPath(), "_api/gharial"))
Expand Down
2 changes: 1 addition & 1 deletion graph_edge_collections.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,5 @@ type VertexConstraints struct {
// CreateEdgeCollectionOptions contains optional parameters for creating a new edge collection
type CreateEdgeCollectionOptions struct {
// Satellites contains an array of collection names that will be used to create SatelliteCollections for a Hybrid (Disjoint) SmartGraph (Enterprise Edition only)
Satellites []string `json:"satellites"`
Satellites []string `json:"satellites,omitempty"`
}
2 changes: 1 addition & 1 deletion graph_vertex_collections.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,5 @@ type GraphVertexCollections interface {
// CreateVertexCollectionOptions contains optional parameters for creating a new vertex collection
type CreateVertexCollectionOptions struct {
// Satellites contains an array of collection names that will be used to create SatelliteCollections for a Hybrid (Disjoint) SmartGraph (Enterprise Edition only)
Satellites []string `json:"satellites"`
Satellites []string `json:"satellites,omitempty"`
}
74 changes: 74 additions & 0 deletions test/edge_collection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,80 @@ func TestCreateEdgeCollection(t *testing.T) {
}
}

// TestCreateSatelliteEdgeCollection creates a graph and then adds an Satellite edge collection in it
func TestCreateSatelliteEdgeCollection(t *testing.T) {
ctx := context.Background()

c := createClientFromEnv(t, true)
EnsureVersion(t, ctx, c).CheckVersion(MinimumVersion("3.9.0")).Cluster().Enterprise()

db := ensureDatabase(nil, c, "edge_collection_test", nil, t)

name := "test_create_sat_edge_collection"
options := driver.CreateGraphOptions{
IsSmart: true,
SmartGraphAttribute: "test",
}
g, err := db.CreateGraph(ctx, name, &options)
if err != nil {
t.Fatalf("Failed to create graph '%s': %s", name, describe(err))
}

// List edge collections, must be empty
if list, _, err := g.EdgeCollections(nil); err != nil {
t.Errorf("EdgeCollections failed: %s", describe(err))
} else if len(list) > 0 {
t.Errorf("EdgeCollections return %d edge collections, expected 0", len(list))
}

// Now create an edge collection
colName := "create_sat_edge_collection"
col1Name := "sat_edge_collection1"
col2Name := "sat_edge_collection2"

opt := driver.CreateEdgeCollectionOptions{Satellites: []string{col1Name}}
if ec, err := g.CreateEdgeCollectionWithOptions(nil, colName, driver.VertexConstraints{From: []string{col1Name}, To: []string{col2Name}}, opt); err != nil {
t.Errorf("CreateEdgeCollection failed: %s", describe(err))
} else if ec.Name() != colName {
t.Errorf("Invalid name, expected '%s', got '%s'", colName, ec.Name())
}

assertCollection(nil, db, colName, t)
assertCollection(nil, db, col1Name, t)
assertCollection(nil, db, col2Name, t)

if list, constraints, err := g.EdgeCollections(nil); err != nil {
t.Errorf("EdgeCollections failed: %s", describe(err))
} else {
if len(list) != 1 {
t.Errorf("EdgeCollections return %d edge collections, expected 1", len(list))
} else if list[0].Name() != colName {
t.Errorf("Invalid list[0].name, expected '%s', got '%s'", colName, list[0].Name())
}
if len(constraints) != 1 {
t.Errorf("EdgeCollections return %d constraints, expected 1", len(constraints))
} else {
if strings.Join(constraints[0].From, ",") != col1Name {
t.Errorf("Invalid constraints[0].From, expected ['%s'], got %q", col1Name, constraints[0].From)
}
if strings.Join(constraints[0].To, ",") != col2Name {
t.Errorf("Invalid constraints[0].From, expected ['%s'], got %q", col2Name, constraints[0].To)
}

prop, err := list[0].Properties(ctx)
if err != nil {
t.Errorf("VertexCollections Properties failed: %s", describe(err))
}
if !prop.IsSatellite() {
t.Errorf("Collection %s is not satellite", colName)
}
}
}

// revert
g.Remove(ctx)
}

// TestRemoveEdgeCollection creates a graph and then adds an edge collection in it and then removes the edge collection.
func TestRemoveEdgeCollection(t *testing.T) {
c := createClientFromEnv(t, true)
Expand Down
53 changes: 53 additions & 0 deletions test/graph_creation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,3 +315,56 @@ func TestGraphCreation(t *testing.T) {
require.True(t, graphs[0].IsDisjoint())
})
}

func TestHybridSmartGraphCreation(t *testing.T) {
ctx := context.Background()

c := createClientFromEnv(t, true)
EnsureVersion(t, ctx, c).CheckVersion(MinimumVersion("3.9.0")).Cluster().Enterprise()

db := ensureDatabase(ctx, c, databaseName("graph", "create", "hybrid"), nil, t)

name := db.Name() + "_test_create_hybrid_graph"
colName := db.Name() + "_create_hybrid_edge_col"
col1Name := db.Name() + "_sat_edge_col"
col2Name := db.Name() + "_non_sat_edge_col"

options := driver.CreateGraphOptions{
IsSmart: true,
SmartGraphAttribute: "test",
ReplicationFactor: 2,
NumberOfShards: 2,
Satellites: []string{colName, col1Name},
EdgeDefinitions: []driver.EdgeDefinition{{
Collection: colName,
From: []string{col1Name},
To: []string{col2Name},
}},
}
g, err := db.CreateGraph(ctx, name, &options)
if err != nil {
t.Fatalf("Failed to create graph '%s': %s", name, describe(err))
}

graphs, err := db.Graphs(ctx)
require.NoError(t, err)
require.Len(t, graphs, 1)

require.Equal(t, g.Name(), graphs[0].Name())
require.True(t, graphs[0].IsSmart())

for _, collName := range []string{colName, col1Name, col2Name} {
collection, err := db.Collection(ctx, collName)
require.NoError(t, err)

prop, err := collection.Properties(ctx)
require.NoError(t, err)

if collName == col2Name {
require.Equalf(t, 2, prop.ReplicationFactor, "ReplicationFactor mismatch for %s", collName)
require.Equalf(t, 2, prop.NumberOfShards, "NumberOfShards mismatch for %s", collName)
} else {
require.True(t, prop.IsSatellite())
}
}
}
57 changes: 57 additions & 0 deletions test/vertex_collection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,63 @@ func TestCreateVertexCollection(t *testing.T) {
}
}

// TestCreateSatelliteVertexCollection creates a graph and then adds a Satellite vertex collection in it
func TestCreateSatelliteVertexCollection(t *testing.T) {
ctx := context.Background()

c := createClientFromEnv(t, true)
EnsureVersion(t, ctx, c).CheckVersion(MinimumVersion("3.9.0")).Cluster().Enterprise()

db := ensureDatabase(ctx, c, "vertex_collection_test", nil, t)

name := "test_create_satellite_vertex_collection"
options := driver.CreateGraphOptions{
IsSmart: true,
SmartGraphAttribute: "key",
}
g, err := db.CreateGraph(ctx, name, &options)
if err != nil {
t.Fatalf("Failed to create graph '%s': %s", name, describe(err))
}

// List vertex collections, must be empty
if list, err := g.VertexCollections(ctx); err != nil {
t.Errorf("VertexCollections failed: %s", describe(err))
} else if len(list) > 0 {
t.Errorf("VertexCollections return %d vertex collections, expected 0", len(list))
}

satelliteName := "vertex-sat-test"
opt := driver.CreateVertexCollectionOptions{Satellites: []string{satelliteName}}

// Now create a vertex collection
if vc, err := g.CreateVertexCollectionWithOptions(ctx, satelliteName, opt); err != nil {
t.Errorf("CreateVertexCollection failed: %s", describe(err))
} else if vc.Name() != satelliteName {
t.Errorf("Invalid name, expected 'vertex-sat-test', got '%s'", vc.Name())
}

// List vertex collections, must be contain 'person'
if list, err := g.VertexCollections(ctx); err != nil {
t.Errorf("VertexCollections failed: %s", describe(err))
} else if len(list) != 1 {
t.Errorf("VertexCollections return %d vertex collections, expected 1", len(list))
} else if list[0].Name() != satelliteName {
t.Errorf("Invalid list[0].name, expected 'vertex-sat-test', got '%s'", list[0].Name())
} else {
prop, err := list[0].Properties(ctx)
if err != nil {
t.Errorf("VertexCollections Properties failed: %s", describe(err))
}
if !prop.IsSatellite() {
t.Errorf("Collection %s is not satellite", satelliteName)
}
}

// revert
g.Remove(ctx)
}

// TestRemoveVertexCollection creates a graph and then adds an vertex collection in it and then removes the vertex collection.
func TestRemoveVertexCollection(t *testing.T) {
c := createClientFromEnv(t, true)
Expand Down