// // DISCLAIMER // // Copyright 2017 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 // // Author Ewout Prangsma // package driver import ( "context" "encoding/json" "path" "github.com/pkg/errors" ) // Graph opens a connection to an existing graph within the database. // If no graph with given name exists, an NotFoundError is returned. func (d *database) Graph(ctx context.Context, name string) (Graph, error) { escapedName := pathEscape(name) req, err := d.conn.NewRequest("GET", path.Join(d.relPath(), "_api/gharial", escapedName)) if err != nil { return nil, WithStack(err) } resp, err := d.conn.Do(ctx, req) if err != nil { return nil, WithStack(err) } if err := resp.CheckStatus(200); err != nil { return nil, WithStack(err) } var data getGraphResponse if err := resp.ParseBody("", &data); err != nil { return nil, WithStack(err) } g, err := newGraph(data.Graph, d) if err != nil { return nil, WithStack(err) } return g, nil } // GraphExists returns true if a graph with given name exists within the database. func (d *database) GraphExists(ctx context.Context, name string) (bool, error) { escapedName := pathEscape(name) req, err := d.conn.NewRequest("GET", path.Join(d.relPath(), "_api/gharial", escapedName)) if err != nil { return false, WithStack(err) } resp, err := d.conn.Do(ctx, req) if err != nil { return false, WithStack(err) } if err := resp.CheckStatus(200); err == nil { return true, nil } else if IsNotFound(err) { return false, nil } else { return false, WithStack(err) } } type getGraphsResponse struct { Graphs []graphDefinition `json:"graphs,omitempty"` ArangoError } // Graphs returns a list of all graphs in the database. func (d *database) Graphs(ctx context.Context) ([]Graph, error) { req, err := d.conn.NewRequest("GET", path.Join(d.relPath(), "_api/gharial")) if err != nil { return nil, WithStack(err) } resp, err := d.conn.Do(ctx, req) if err != nil { return nil, WithStack(err) } if err := resp.CheckStatus(200); err != nil { return nil, WithStack(err) } var data getGraphsResponse if err := resp.ParseBody("", &data); err != nil { return nil, WithStack(err) } result := make([]Graph, 0, len(data.Graphs)) for _, info := range data.Graphs { g, err := newGraph(info, d) if err != nil { return nil, WithStack(err) } result = append(result, g) } return result, nil } type createGraphOptions struct { Name string `json:"name"` OrphanVertexCollections []string `json:"orphanCollections,omitempty"` EdgeDefinitions []EdgeDefinition `json:"edgeDefinitions,omitempty"` IsSmart bool `json:"isSmart,omitempty"` Options *createGraphAdditionalOptions `json:"options,omitempty"` } type graphReplicationFactor int func (g graphReplicationFactor) MarshalJSON() ([]byte, error) { switch g { case SatelliteGraph: return json.Marshal(replicationFactorSatelliteString) default: return json.Marshal(int(g)) } } func (g *graphReplicationFactor) UnmarshalJSON(data []byte) error { var d int if err := json.Unmarshal(data, &d); err == nil { *g = graphReplicationFactor(d) return nil } var s string if err := json.Unmarshal(data, &s); err != nil { return err } switch s { case replicationFactorSatelliteString: *g = graphReplicationFactor(SatelliteGraph) return nil default: return errors.Errorf("Unsupported type %s", s) } } type createGraphAdditionalOptions struct { // SmartGraphAttribute is the attribute name that is used to smartly shard the vertices of a graph. // Every vertex in this Graph has to have this attribute. // Cannot be modified later. SmartGraphAttribute string `json:"smartGraphAttribute,omitempty"` // NumberOfShards is the number of shards that is used for every collection within this graph. // Cannot be modified later. NumberOfShards int `json:"numberOfShards,omitempty"` // ReplicationFactor is the number of replication factor that is used for every collection within this graph. // Cannot be modified later. ReplicationFactor graphReplicationFactor `json:"replicationFactor,omitempty"` // WriteConcern is the number of min replication factor that is used for every collection within this graph. // Cannot be modified later. WriteConcern int `json:"writeConcern,omitempty"` // 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) // Requires ArangoDB 3.9+ 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. // Deprecated: since ArangoDB 3.9 - please use CreateGraphV2 instead func (d *database) CreateGraph(ctx context.Context, name string, options *CreateGraphOptions) (Graph, error) { input := createGraphOptions{ Name: name, } if options != nil { 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, } } } req, err := d.conn.NewRequest("POST", path.Join(d.relPath(), "_api/gharial")) if err != nil { return nil, WithStack(err) } if _, err := req.SetBody(input); err != nil { return nil, WithStack(err) } resp, err := d.conn.Do(ctx, req) if err != nil { return nil, WithStack(err) } if err := resp.CheckStatus(201, 202); err != nil { return nil, WithStack(err) } var data getGraphResponse if err := resp.ParseBody("", &data); err != nil { return nil, WithStack(err) } g, err := newGraph(data.Graph, d) if err != nil { return nil, WithStack(err) } return g, nil } // CreateGraphV2 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. func (d *database) CreateGraphV2(ctx context.Context, name string, options *CreateGraphOptions) (Graph, error) { input := createGraphOptions{ Name: name, } if options != nil { input.OrphanVertexCollections = options.OrphanVertexCollections input.EdgeDefinitions = options.EdgeDefinitions input.IsSmart = options.IsSmart 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")) if err != nil { return nil, WithStack(err) } if _, err := req.SetBody(input); err != nil { return nil, WithStack(err) } resp, err := d.conn.Do(ctx, req) if err != nil { return nil, WithStack(err) } if err := resp.CheckStatus(201, 202); err != nil { return nil, WithStack(err) } var data getGraphResponse if err := resp.ParseBody("", &data); err != nil { return nil, WithStack(err) } g, err := newGraph(data.Graph, d) if err != nil { return nil, WithStack(err) } return g, nil }