Skip to content

Commit 44f272f

Browse files
authored
GT-570 Allow skipping validation for Database and Collection existence (#575)
1 parent df8dcb5 commit 44f272f

15 files changed

+248
-96
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
- Switch to Go 1.21.5
66
- Disable AF mode in tests (not supported since 3.12)
77
- Remove graph with all collections
8+
- Allow skipping validation for Database and Collection existence
89

910
## [1.6.1](https://github.com/arangodb/go-driver/tree/v1.6.1) (2023-10-31)
1011
- Add support for getting license

client_databases_impl.go

+15-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2017 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2017-2023 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -17,8 +17,6 @@
1717
//
1818
// Copyright holder is ArangoDB GmbH, Cologne, Germany
1919
//
20-
// Author Ewout Prangsma
21-
//
2220

2321
package driver
2422

@@ -30,6 +28,19 @@ import (
3028
// Database opens a connection to an existing database.
3129
// If no database with given name exists, an NotFoundError is returned.
3230
func (c *client) Database(ctx context.Context, name string) (Database, error) {
31+
db, err := newDatabase(name, c.conn)
32+
if err != nil {
33+
return nil, WithStack(err)
34+
}
35+
36+
if ctx != nil {
37+
if v := ctx.Value(keySkipExistCheck); v != nil {
38+
if skipIfExistCheck, ok := v.(bool); ok && skipIfExistCheck {
39+
return db, nil
40+
}
41+
}
42+
}
43+
3344
escapedName := pathEscape(name)
3445
req, err := c.conn.NewRequest("GET", path.Join("_db", escapedName, "_api/database/current"))
3546
if err != nil {
@@ -42,10 +53,7 @@ func (c *client) Database(ctx context.Context, name string) (Database, error) {
4253
if err := resp.CheckStatus(200); err != nil {
4354
return nil, WithStack(err)
4455
}
45-
db, err := newDatabase(name, c.conn)
46-
if err != nil {
47-
return nil, WithStack(err)
48-
}
56+
4957
return db, nil
5058
}
5159

context.go

+7
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ const (
6969
keyRefillIndexCaches ContextKey = "arangodb-driver-refill-index-caches"
7070
keyAsyncRequest ContextKey = "arangodb-async-request"
7171
keyAsyncID ContextKey = "arangodb-async-id"
72+
keySkipExistCheck ContextKey = "arangodb-skip-exist-check"
7273
)
7374

7475
type OverwriteMode string
@@ -307,6 +308,12 @@ func WithAsyncID(parent context.Context, asyncID string) context.Context {
307308
return context.WithValue(contextOrBackground(parent), keyAsyncID, asyncID)
308309
}
309310

311+
// WithSkipExistCheck is used to disable validation for resource existence
312+
// e.g.: ClientDatabases.Database will do not call the additional check to ArangoDB for ensuring that DB exist
313+
func WithSkipExistCheck(parent context.Context, value bool) context.Context {
314+
return context.WithValue(contextOrBackground(parent), keySkipExistCheck, value)
315+
}
316+
310317
type contextSettings struct {
311318
Silent bool
312319
WaitForSync bool

database_collections_impl.go

+14-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2017 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2017-2023 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -17,8 +17,6 @@
1717
//
1818
// Copyright holder is ArangoDB GmbH, Cologne, Germany
1919
//
20-
// Author Ewout Prangsma
21-
//
2220

2321
package driver
2422

@@ -30,6 +28,19 @@ import (
3028
// Collection opens a connection to an existing collection within the database.
3129
// If no collection with given name exists, an NotFoundError is returned.
3230
func (d *database) Collection(ctx context.Context, name string) (Collection, error) {
31+
coll, err := newCollection(name, d)
32+
if err != nil {
33+
return nil, WithStack(err)
34+
}
35+
36+
if ctx != nil {
37+
if v := ctx.Value(keySkipExistCheck); v != nil {
38+
if skipIfExistCheck, ok := v.(bool); ok && skipIfExistCheck {
39+
return coll, nil
40+
}
41+
}
42+
}
43+
3344
escapedName := pathEscape(name)
3445
req, err := d.conn.NewRequest("GET", path.Join(d.relPath(), "_api/collection", escapedName))
3546
if err != nil {
@@ -42,10 +53,6 @@ func (d *database) Collection(ctx context.Context, name string) (Collection, err
4253
if err := resp.CheckStatus(200); err != nil {
4354
return nil, WithStack(err)
4455
}
45-
coll, err := newCollection(name, d)
46-
if err != nil {
47-
return nil, WithStack(err)
48-
}
4956
return coll, nil
5057
}
5158

test/collection_test.go

+16
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,22 @@ func assertCollection(ctx context.Context, db driver.Database, name string, t *t
5959
return c
6060
}
6161

62+
func TestGetCollection(t *testing.T) {
63+
c := createClient(t, nil)
64+
db := ensureDatabase(nil, c, "collection_get_test", nil, t)
65+
66+
name := "test_wrong_collection"
67+
68+
_, err := db.Collection(nil, name)
69+
require.Error(t, err)
70+
71+
_, err = db.Collection(driver.WithSkipExistCheck(nil, false), name)
72+
require.Error(t, err)
73+
74+
_, err = db.Collection(driver.WithSkipExistCheck(nil, true), name)
75+
require.NoError(t, err)
76+
}
77+
6278
// TestCreateCollection creates a collection and then checks that it exists.
6379
func TestCreateCollection(t *testing.T) {
6480
c := createClient(t, nil)

test/database_test.go

+15
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,21 @@ func skipIfEngineType(t *testing.T, db driver.Database, engineType driver.Engine
7474
}
7575
}
7676

77+
func TestGetDatabase(t *testing.T) {
78+
c := createClient(t, nil)
79+
80+
name := "test_wrong_database"
81+
82+
_, err := c.Database(nil, name)
83+
require.Error(t, err)
84+
85+
_, err = c.Database(driver.WithSkipExistCheck(nil, false), name)
86+
require.Error(t, err)
87+
88+
_, err = c.Database(driver.WithSkipExistCheck(nil, true), name)
89+
require.NoError(t, err)
90+
}
91+
7792
// TestCreateDatabase creates a database and then checks that it exists.
7893
func TestCreateDatabase(t *testing.T) {
7994
c := createClient(t, nil)

v2/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## [master](https://github.com/arangodb/go-driver/tree/master) (N/A)
44
- Switch to Go 1.21.5
55
- Disable AF mode in tests (not supported since 3.12)
6+
- Allow skipping validation for Database and Collection existence
67

78
## [2.0.3](https://github.com/arangodb/go-driver/tree/v2.0.3) (2023-10-31)
89
- Add optional status code checks. Consistent return of response

v2/arangodb/client_database.go

+12-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2020 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2020-2023 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -17,8 +17,6 @@
1717
//
1818
// Copyright holder is ArangoDB GmbH, Cologne, Germany
1919
//
20-
// Author Adam Janikowski
21-
//
2220

2321
package arangodb
2422

@@ -29,8 +27,13 @@ import (
2927
type ClientDatabase interface {
3028
// Database opens a connection to an existing database.
3129
// If no database with given name exists, an NotFoundError is returned.
30+
// deprecated: use GetDatabase instead
3231
Database(ctx context.Context, name string) (Database, error)
3332

33+
// GetDatabase opens a connection to an existing database.
34+
// If no database with given name exists, an NotFoundError is returned.
35+
GetDatabase(ctx context.Context, name string, options *GetDatabaseOptions) (Database, error)
36+
3437
// DatabaseExists returns true if a database with given name exists.
3538
DatabaseExists(ctx context.Context, name string) (bool, error)
3639

@@ -63,6 +66,12 @@ type CreateDatabaseOptions struct {
6366
Options CreateDatabaseDefaultOptions `json:"options,omitempty"`
6467
}
6568

69+
// GetDatabaseOptions contains options that customize the getting of a database.
70+
type GetDatabaseOptions struct {
71+
// SkipExistCheck skips checking if database exists
72+
SkipExistCheck bool `json:"skipExistCheck,omitempty"`
73+
}
74+
6675
// DatabaseReplicationVersion defines replication protocol version to use for this database
6776
// Available since ArangoDB version 3.11
6877
// Note: this feature is still considered experimental and should not be used in production

v2/arangodb/client_database_impl.go

+13-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2020 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2020-2023 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -17,8 +17,6 @@
1717
//
1818
// Copyright holder is ArangoDB GmbH, Cologne, Germany
1919
//
20-
// Author Adam Janikowski
21-
//
2220

2321
package arangodb
2422

@@ -79,7 +77,7 @@ func (c clientDatabase) AccessibleDatabases(ctx context.Context) ([]Database, er
7977
}
8078

8179
func (c clientDatabase) DatabaseExists(ctx context.Context, name string) (bool, error) {
82-
_, err := c.Database(ctx, name)
80+
_, err := c.GetDatabase(ctx, name, nil)
8381
if err == nil {
8482
return true, nil
8583
}
@@ -97,6 +95,16 @@ func (c clientDatabase) Databases(ctx context.Context) ([]Database, error) {
9795
}
9896

9997
func (c clientDatabase) Database(ctx context.Context, name string) (Database, error) {
98+
return c.GetDatabase(ctx, name, nil)
99+
}
100+
101+
func (c clientDatabase) GetDatabase(ctx context.Context, name string, options *GetDatabaseOptions) (Database, error) {
102+
db := newDatabase(c.client, name)
103+
104+
if options != nil && options.SkipExistCheck {
105+
return db, nil
106+
}
107+
100108
url := connection.NewUrl("_db", name, "_api", "database", "current")
101109

102110
var response struct {
@@ -111,7 +119,7 @@ func (c clientDatabase) Database(ctx context.Context, name string) (Database, er
111119

112120
switch code := resp.Code(); code {
113121
case http.StatusOK:
114-
return newDatabase(c.client, name), nil
122+
return db, nil
115123
default:
116124
return nil, response.AsArangoErrorWithCode(code)
117125
}

v2/arangodb/database_collection.go

+10
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,13 @@ import (
2727
type DatabaseCollection interface {
2828
// Collection opens a connection to an existing collection within the database.
2929
// If no collection with given name exists, an NotFoundError is returned.
30+
// deprecated: use GetCollection instead
3031
Collection(ctx context.Context, name string) (Collection, error)
3132

33+
// GetCollection opens a connection to an existing collection within the database.
34+
// If no collection with given name exists, an NotFoundError is returned.
35+
GetCollection(ctx context.Context, name string, options *GetCollectionOptions) (Collection, error)
36+
3237
// CollectionExists returns true if a collection with given name exists within the database.
3338
CollectionExists(ctx context.Context, name string) (bool, error)
3439

@@ -43,3 +48,8 @@ type DatabaseCollection interface {
4348
// If a collection with given name already exists within the database, a DuplicateError is returned.
4449
CreateCollectionWithOptions(ctx context.Context, name string, props *CreateCollectionProperties, options *CreateCollectionOptions) (Collection, error)
4550
}
51+
52+
type GetCollectionOptions struct {
53+
// SkipExistCheck skips checking if collection exists
54+
SkipExistCheck bool `json:"skipExistCheck,omitempty"`
55+
}

v2/arangodb/database_collection_impl.go

+12-2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ type databaseCollection struct {
4444
}
4545

4646
func (d databaseCollection) Collection(ctx context.Context, name string) (Collection, error) {
47+
return d.GetCollection(ctx, name, nil)
48+
}
49+
50+
func (d databaseCollection) GetCollection(ctx context.Context, name string, options *GetCollectionOptions) (Collection, error) {
51+
col := newCollection(d.db, name)
52+
53+
if options != nil && options.SkipExistCheck {
54+
return col, nil
55+
}
56+
4757
url := d.db.url("_api", "collection", name)
4858

4959
var response struct {
@@ -57,14 +67,14 @@ func (d databaseCollection) Collection(ctx context.Context, name string) (Collec
5767

5868
switch code := resp.Code(); code {
5969
case http.StatusOK:
60-
return newCollection(d.db, name), nil
70+
return col, nil
6171
default:
6272
return nil, response.AsArangoErrorWithCode(code)
6373
}
6474
}
6575

6676
func (d databaseCollection) CollectionExists(ctx context.Context, name string) (bool, error) {
67-
_, err := d.Collection(ctx, name)
77+
_, err := d.GetCollection(ctx, name, nil)
6878
if err == nil {
6979
return true, nil
7080
}

0 commit comments

Comments
 (0)