1
2
3
4
5
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
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
46 type ListDatabasesResult struct {
47
48 Databases []databaseRecord
49
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
128 func NewListDatabases(filter bsoncore.Document) *ListDatabases {
129 return &ListDatabases{
130 filter: filter,
131 }
132 }
133
134
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
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
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
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
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
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
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
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
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
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
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
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
291
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
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
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
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