...

Source file src/go.mongodb.org/mongo-driver/x/mongo/driver/operation/listDatabases.go

Documentation: go.mongodb.org/mongo-driver/x/mongo/driver/operation

     1  // Copyright (C) MongoDB, Inc. 2019-present.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"); you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
     6  
     7  package operation
     8  
     9  import (
    10  	"context"
    11  	"errors"
    12  	"fmt"
    13  	"time"
    14  
    15  	"go.mongodb.org/mongo-driver/bson"
    16  	"go.mongodb.org/mongo-driver/event"
    17  	"go.mongodb.org/mongo-driver/internal/driverutil"
    18  	"go.mongodb.org/mongo-driver/mongo/description"
    19  	"go.mongodb.org/mongo-driver/mongo/readpref"
    20  	"go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
    21  	"go.mongodb.org/mongo-driver/x/mongo/driver"
    22  	"go.mongodb.org/mongo-driver/x/mongo/driver/session"
    23  )
    24  
    25  // ListDatabases performs a listDatabases operation.
    26  type ListDatabases struct {
    27  	filter              bsoncore.Document
    28  	authorizedDatabases *bool
    29  	nameOnly            *bool
    30  	session             *session.Client
    31  	clock               *session.ClusterClock
    32  	monitor             *event.CommandMonitor
    33  	database            string
    34  	deployment          driver.Deployment
    35  	readPreference      *readpref.ReadPref
    36  	retry               *driver.RetryMode
    37  	selector            description.ServerSelector
    38  	crypt               driver.Crypt
    39  	serverAPI           *driver.ServerAPIOptions
    40  	timeout             *time.Duration
    41  
    42  	result ListDatabasesResult
    43  }
    44  
    45  // ListDatabasesResult represents a listDatabases result returned by the server.
    46  type ListDatabasesResult struct {
    47  	// An array of documents, one document for each database
    48  	Databases []databaseRecord
    49  	// The sum of the size of all the database files on disk in bytes.
    50  	TotalSize int64
    51  }
    52  
    53  type databaseRecord struct {
    54  	Name       string
    55  	SizeOnDisk int64 `bson:"sizeOnDisk"`
    56  	Empty      bool
    57  }
    58  
    59  func buildListDatabasesResult(response bsoncore.Document) (ListDatabasesResult, error) {
    60  	elements, err := response.Elements()
    61  	if err != nil {
    62  		return ListDatabasesResult{}, err
    63  	}
    64  	ir := ListDatabasesResult{}
    65  	for _, element := range elements {
    66  		switch element.Key() {
    67  		case "totalSize":
    68  			var ok bool
    69  			ir.TotalSize, ok = element.Value().AsInt64OK()
    70  			if !ok {
    71  				return ir, fmt.Errorf("response field 'totalSize' is type int64, but received BSON type %s: %s", element.Value().Type, element.Value())
    72  			}
    73  		case "databases":
    74  			arr, ok := element.Value().ArrayOK()
    75  			if !ok {
    76  				return ir, fmt.Errorf("response field 'databases' is type array, but received BSON type %s", element.Value().Type)
    77  			}
    78  
    79  			var tmp bsoncore.Document
    80  			err := bson.Unmarshal(arr, &tmp)
    81  			if err != nil {
    82  				return ir, err
    83  			}
    84  
    85  			records, err := tmp.Elements()
    86  			if err != nil {
    87  				return ir, err
    88  			}
    89  
    90  			ir.Databases = make([]databaseRecord, len(records))
    91  			for i, val := range records {
    92  				valueDoc, ok := val.Value().DocumentOK()
    93  				if !ok {
    94  					return ir, fmt.Errorf("'databases' element is type document, but received BSON type %s", val.Value().Type)
    95  				}
    96  
    97  				elems, err := valueDoc.Elements()
    98  				if err != nil {
    99  					return ir, err
   100  				}
   101  
   102  				for _, elem := range elems {
   103  					switch elem.Key() {
   104  					case "name":
   105  						ir.Databases[i].Name, ok = elem.Value().StringValueOK()
   106  						if !ok {
   107  							return ir, fmt.Errorf("response field 'name' is type string, but received BSON type %s", elem.Value().Type)
   108  						}
   109  					case "sizeOnDisk":
   110  						ir.Databases[i].SizeOnDisk, ok = elem.Value().AsInt64OK()
   111  						if !ok {
   112  							return ir, fmt.Errorf("response field 'sizeOnDisk' is type int64, but received BSON type %s", elem.Value().Type)
   113  						}
   114  					case "empty":
   115  						ir.Databases[i].Empty, ok = elem.Value().BooleanOK()
   116  						if !ok {
   117  							return ir, fmt.Errorf("response field 'empty' is type bool, but received BSON type %s", elem.Value().Type)
   118  						}
   119  					}
   120  				}
   121  			}
   122  		}
   123  	}
   124  	return ir, nil
   125  }
   126  
   127  // NewListDatabases constructs and returns a new ListDatabases.
   128  func NewListDatabases(filter bsoncore.Document) *ListDatabases {
   129  	return &ListDatabases{
   130  		filter: filter,
   131  	}
   132  }
   133  
   134  // Result returns the result of executing this operation.
   135  func (ld *ListDatabases) Result() ListDatabasesResult { return ld.result }
   136  
   137  func (ld *ListDatabases) processResponse(info driver.ResponseInfo) error {
   138  	var err error
   139  
   140  	ld.result, err = buildListDatabasesResult(info.ServerResponse)
   141  	return err
   142  
   143  }
   144  
   145  // Execute runs this operations and returns an error if the operation did not execute successfully.
   146  func (ld *ListDatabases) Execute(ctx context.Context) error {
   147  	if ld.deployment == nil {
   148  		return errors.New("the ListDatabases operation must have a Deployment set before Execute can be called")
   149  	}
   150  
   151  	return driver.Operation{
   152  		CommandFn:         ld.command,
   153  		ProcessResponseFn: ld.processResponse,
   154  
   155  		Client:         ld.session,
   156  		Clock:          ld.clock,
   157  		CommandMonitor: ld.monitor,
   158  		Database:       ld.database,
   159  		Deployment:     ld.deployment,
   160  		ReadPreference: ld.readPreference,
   161  		RetryMode:      ld.retry,
   162  		Type:           driver.Read,
   163  		Selector:       ld.selector,
   164  		Crypt:          ld.crypt,
   165  		ServerAPI:      ld.serverAPI,
   166  		Timeout:        ld.timeout,
   167  		Name:           driverutil.ListDatabasesOp,
   168  	}.Execute(ctx)
   169  
   170  }
   171  
   172  func (ld *ListDatabases) command(dst []byte, _ description.SelectedServer) ([]byte, error) {
   173  	dst = bsoncore.AppendInt32Element(dst, "listDatabases", 1)
   174  	if ld.filter != nil {
   175  
   176  		dst = bsoncore.AppendDocumentElement(dst, "filter", ld.filter)
   177  	}
   178  	if ld.nameOnly != nil {
   179  
   180  		dst = bsoncore.AppendBooleanElement(dst, "nameOnly", *ld.nameOnly)
   181  	}
   182  	if ld.authorizedDatabases != nil {
   183  
   184  		dst = bsoncore.AppendBooleanElement(dst, "authorizedDatabases", *ld.authorizedDatabases)
   185  	}
   186  
   187  	return dst, nil
   188  }
   189  
   190  // Filter determines what results are returned from listDatabases.
   191  func (ld *ListDatabases) Filter(filter bsoncore.Document) *ListDatabases {
   192  	if ld == nil {
   193  		ld = new(ListDatabases)
   194  	}
   195  
   196  	ld.filter = filter
   197  	return ld
   198  }
   199  
   200  // NameOnly specifies whether to only return database names.
   201  func (ld *ListDatabases) NameOnly(nameOnly bool) *ListDatabases {
   202  	if ld == nil {
   203  		ld = new(ListDatabases)
   204  	}
   205  
   206  	ld.nameOnly = &nameOnly
   207  	return ld
   208  }
   209  
   210  // AuthorizedDatabases specifies whether to only return databases which the user is authorized to use."
   211  func (ld *ListDatabases) AuthorizedDatabases(authorizedDatabases bool) *ListDatabases {
   212  	if ld == nil {
   213  		ld = new(ListDatabases)
   214  	}
   215  
   216  	ld.authorizedDatabases = &authorizedDatabases
   217  	return ld
   218  }
   219  
   220  // Session sets the session for this operation.
   221  func (ld *ListDatabases) Session(session *session.Client) *ListDatabases {
   222  	if ld == nil {
   223  		ld = new(ListDatabases)
   224  	}
   225  
   226  	ld.session = session
   227  	return ld
   228  }
   229  
   230  // ClusterClock sets the cluster clock for this operation.
   231  func (ld *ListDatabases) ClusterClock(clock *session.ClusterClock) *ListDatabases {
   232  	if ld == nil {
   233  		ld = new(ListDatabases)
   234  	}
   235  
   236  	ld.clock = clock
   237  	return ld
   238  }
   239  
   240  // CommandMonitor sets the monitor to use for APM events.
   241  func (ld *ListDatabases) CommandMonitor(monitor *event.CommandMonitor) *ListDatabases {
   242  	if ld == nil {
   243  		ld = new(ListDatabases)
   244  	}
   245  
   246  	ld.monitor = monitor
   247  	return ld
   248  }
   249  
   250  // Database sets the database to run this operation against.
   251  func (ld *ListDatabases) Database(database string) *ListDatabases {
   252  	if ld == nil {
   253  		ld = new(ListDatabases)
   254  	}
   255  
   256  	ld.database = database
   257  	return ld
   258  }
   259  
   260  // Deployment sets the deployment to use for this operation.
   261  func (ld *ListDatabases) Deployment(deployment driver.Deployment) *ListDatabases {
   262  	if ld == nil {
   263  		ld = new(ListDatabases)
   264  	}
   265  
   266  	ld.deployment = deployment
   267  	return ld
   268  }
   269  
   270  // ReadPreference set the read preference used with this operation.
   271  func (ld *ListDatabases) ReadPreference(readPreference *readpref.ReadPref) *ListDatabases {
   272  	if ld == nil {
   273  		ld = new(ListDatabases)
   274  	}
   275  
   276  	ld.readPreference = readPreference
   277  	return ld
   278  }
   279  
   280  // ServerSelector sets the selector used to retrieve a server.
   281  func (ld *ListDatabases) ServerSelector(selector description.ServerSelector) *ListDatabases {
   282  	if ld == nil {
   283  		ld = new(ListDatabases)
   284  	}
   285  
   286  	ld.selector = selector
   287  	return ld
   288  }
   289  
   290  // Retry enables retryable mode for this operation. Retries are handled automatically in driver.Operation.Execute based
   291  // on how the operation is set.
   292  func (ld *ListDatabases) Retry(retry driver.RetryMode) *ListDatabases {
   293  	if ld == nil {
   294  		ld = new(ListDatabases)
   295  	}
   296  
   297  	ld.retry = &retry
   298  	return ld
   299  }
   300  
   301  // Crypt sets the Crypt object to use for automatic encryption and decryption.
   302  func (ld *ListDatabases) Crypt(crypt driver.Crypt) *ListDatabases {
   303  	if ld == nil {
   304  		ld = new(ListDatabases)
   305  	}
   306  
   307  	ld.crypt = crypt
   308  	return ld
   309  }
   310  
   311  // ServerAPI sets the server API version for this operation.
   312  func (ld *ListDatabases) ServerAPI(serverAPI *driver.ServerAPIOptions) *ListDatabases {
   313  	if ld == nil {
   314  		ld = new(ListDatabases)
   315  	}
   316  
   317  	ld.serverAPI = serverAPI
   318  	return ld
   319  }
   320  
   321  // Timeout sets the timeout for this operation.
   322  func (ld *ListDatabases) Timeout(timeout *time.Duration) *ListDatabases {
   323  	if ld == nil {
   324  		ld = new(ListDatabases)
   325  	}
   326  
   327  	ld.timeout = timeout
   328  	return ld
   329  }
   330  

View as plain text