/cosmos/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/list_collections.go

https://github.com/scality/Zenko · Go · 141 lines · 105 code · 24 blank · 12 comment · 28 complexity · 45c89eceaf6d4aff54abea30ae52e8bb MD5 · raw file

  1. // Copyright (C) MongoDB, Inc. 2017-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. package driver
  7. import (
  8. "context"
  9. "errors"
  10. "go.mongodb.org/mongo-driver/mongo/options"
  11. "go.mongodb.org/mongo-driver/x/bsonx"
  12. "go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
  13. "go.mongodb.org/mongo-driver/x/mongo/driver/session"
  14. "go.mongodb.org/mongo-driver/x/mongo/driver/topology"
  15. "go.mongodb.org/mongo-driver/x/mongo/driver/uuid"
  16. "go.mongodb.org/mongo-driver/x/network/command"
  17. "go.mongodb.org/mongo-driver/x/network/connection"
  18. "go.mongodb.org/mongo-driver/x/network/description"
  19. )
  20. // ErrFilterType is thrown when a non-string filter is specified.
  21. var ErrFilterType = errors.New("filter must be a string")
  22. // ListCollections handles the full cycle dispatch and execution of a listCollections command against the provided
  23. // topology.
  24. func ListCollections(
  25. ctx context.Context,
  26. cmd command.ListCollections,
  27. topo *topology.Topology,
  28. selector description.ServerSelector,
  29. clientID uuid.UUID,
  30. pool *session.Pool,
  31. opts ...*options.ListCollectionsOptions,
  32. ) (*ListCollectionsBatchCursor, error) {
  33. ss, err := topo.SelectServer(ctx, selector)
  34. if err != nil {
  35. return nil, err
  36. }
  37. conn, err := ss.Connection(ctx)
  38. if err != nil {
  39. return nil, err
  40. }
  41. defer conn.Close()
  42. if ss.Description().WireVersion.Max < 3 {
  43. return legacyListCollections(ctx, cmd, ss, conn)
  44. }
  45. rp, err := getReadPrefBasedOnTransaction(cmd.ReadPref, cmd.Session)
  46. if err != nil {
  47. return nil, err
  48. }
  49. cmd.ReadPref = rp
  50. // If no explicit session and deployment supports sessions, start implicit session.
  51. if cmd.Session == nil && topo.SupportsSessions() {
  52. cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
  53. if err != nil {
  54. return nil, err
  55. }
  56. }
  57. lc := options.MergeListCollectionsOptions(opts...)
  58. if lc.NameOnly != nil {
  59. cmd.Opts = append(cmd.Opts, bsonx.Elem{"nameOnly", bsonx.Boolean(*lc.NameOnly)})
  60. }
  61. res, err := cmd.RoundTrip(ctx, ss.Description(), conn)
  62. if err != nil {
  63. closeImplicitSession(cmd.Session)
  64. return nil, err
  65. }
  66. batchCursor, err := NewBatchCursor(bsoncore.Document(res), cmd.Session, cmd.Clock, ss.Server, cmd.CursorOpts...)
  67. if err != nil {
  68. closeImplicitSession(cmd.Session)
  69. return nil, err
  70. }
  71. return NewListCollectionsBatchCursor(batchCursor)
  72. }
  73. func legacyListCollections(
  74. ctx context.Context,
  75. cmd command.ListCollections,
  76. ss *topology.SelectedServer,
  77. conn connection.Connection,
  78. ) (*ListCollectionsBatchCursor, error) {
  79. filter, err := transformFilter(cmd.Filter, cmd.DB)
  80. if err != nil {
  81. return nil, err
  82. }
  83. findCmd := command.Find{
  84. NS: command.NewNamespace(cmd.DB, "system.namespaces"),
  85. ReadPref: cmd.ReadPref,
  86. Filter: filter,
  87. }
  88. // don't need registry because it's used to create BSON docs for find options that don't exist in this case
  89. batchCursor, err := legacyFind(ctx, findCmd, nil, ss, conn)
  90. if err != nil {
  91. return nil, err
  92. }
  93. return NewLegacyListCollectionsBatchCursor(batchCursor)
  94. }
  95. // modify the user-supplied filter to prefix the "name" field with the database name.
  96. // returns the original filter if the name field is not present or a copy with the modified name field if it is
  97. func transformFilter(filter bsonx.Doc, dbName string) (bsonx.Doc, error) {
  98. regexFilter := bsonx.Doc{
  99. {"name", bsonx.Regex("^[^$]*$", "")},
  100. }
  101. if filter == nil {
  102. return regexFilter, nil
  103. }
  104. converted := filter
  105. if nameIdx := filter.IndexOf("name"); nameIdx != -1 {
  106. name, ok := filter[nameIdx].Value.StringValueOK()
  107. if !ok {
  108. return nil, ErrFilterType
  109. }
  110. converted = filter.Copy()
  111. converted[nameIdx].Value = bsonx.String(dbName + "." + name)
  112. }
  113. filterArr := bsonx.Arr{bsonx.Document(regexFilter), bsonx.Document(converted)}
  114. return bsonx.Doc{
  115. {"$and", bsonx.Array(filterArr)},
  116. }, nil
  117. }