github.com/ydb-platform/ydb-go-sdk/v3@v3.57.0/sugar/path.go (about) 1 package sugar 2 3 import ( 4 "context" 5 "fmt" 6 "path" 7 "strings" 8 9 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" 10 "github.com/ydb-platform/ydb-go-sdk/v3/scheme" 11 "github.com/ydb-platform/ydb-go-sdk/v3/table" 12 "github.com/ydb-platform/ydb-go-sdk/v3/topic" 13 ) 14 15 const ( 16 sysDirectory = ".sys" 17 ) 18 19 type dbName interface { 20 Name() string 21 } 22 23 type dbScheme interface { 24 Scheme() scheme.Client 25 } 26 27 type dbTable interface { 28 Table() table.Client 29 } 30 31 type dbTopic interface { 32 Topic() topic.Client 33 } 34 35 type dbForMakeRecursive interface { 36 dbName 37 dbScheme 38 } 39 40 type dbFoRemoveRecursive interface { 41 dbName 42 dbScheme 43 dbTable 44 dbTopic 45 } 46 47 // MakeRecursive creates path inside database 48 // pathToCreate is a database root relative path 49 // MakeRecursive method equal bash command `mkdir -p ~/path/to/create` 50 // where `~` - is a root of database 51 func MakeRecursive(ctx context.Context, db dbForMakeRecursive, pathToCreate string) error { 52 if strings.HasPrefix(pathToCreate, sysDirectory+"/") { 53 return xerrors.WithStackTrace( 54 fmt.Errorf("making directory %q inside system path %q not supported", pathToCreate, sysDirectory), 55 ) 56 } 57 58 absPath := path.Join(db.Name(), pathToCreate) 59 60 err := db.Scheme().MakeDirectory(ctx, absPath) 61 if err != nil { 62 return xerrors.WithStackTrace( 63 fmt.Errorf("cannot make directory %q: %w", absPath, err), 64 ) 65 } 66 67 info, err := db.Scheme().DescribePath(ctx, absPath) 68 if err != nil { 69 return xerrors.WithStackTrace( 70 fmt.Errorf("cannot describe path %q: %w", absPath, err), 71 ) 72 } 73 74 switch info.Type { 75 case 76 scheme.EntryDatabase, 77 scheme.EntryDirectory: 78 return nil 79 default: 80 return xerrors.WithStackTrace( 81 fmt.Errorf("entry %q exists but it is not a directory: %s", absPath, info.Type), 82 ) 83 } 84 } 85 86 // RemoveRecursive remove selected directory or table names in database. 87 // pathToRemove is a database root relative path 88 // All database entities in prefix path will remove if names list is empty. 89 // Empty prefix means than use root of database. 90 // RemoveRecursive method equal bash command `rm -rf ~/path/to/remove` 91 // where `~` - is a root of database 92 func RemoveRecursive(ctx context.Context, db dbFoRemoveRecursive, pathToRemove string) error { 93 fullSysTablePath := path.Join(db.Name(), sysDirectory) 94 var rmPath func(int, string) error 95 rmPath = func(i int, p string) error { 96 if exists, err := IsDirectoryExists(ctx, db.Scheme(), p); err != nil { 97 return xerrors.WithStackTrace( 98 fmt.Errorf("check directory %q exists failed: %w", p, err), 99 ) 100 } else if !exists { 101 return nil 102 } 103 104 entry, err := db.Scheme().DescribePath(ctx, p) 105 if err != nil { 106 return xerrors.WithStackTrace( 107 fmt.Errorf("cannot describe path %q: %w", p, err), 108 ) 109 } 110 111 if entry.Type != scheme.EntryDirectory && entry.Type != scheme.EntryDatabase { 112 return nil 113 } 114 115 dir, err := db.Scheme().ListDirectory(ctx, p) 116 if err != nil { 117 return xerrors.WithStackTrace( 118 fmt.Errorf("listing directory %q failed: %w", p, err), 119 ) 120 } 121 122 for j := range dir.Children { 123 pt := path.Join(p, dir.Children[j].Name) 124 if pt == fullSysTablePath { 125 continue 126 } 127 switch t := dir.Children[j].Type; t { 128 case scheme.EntryDirectory: 129 if err = rmPath(i+1, pt); err != nil { 130 return xerrors.WithStackTrace( 131 fmt.Errorf("recursive removing directory %q failed: %w", pt, err), 132 ) 133 } 134 135 case scheme.EntryTable, scheme.EntryColumnTable: 136 err = db.Table().Do(ctx, func(ctx context.Context, session table.Session) (err error) { 137 return session.DropTable(ctx, pt) 138 }, table.WithIdempotent()) 139 if err != nil { 140 return xerrors.WithStackTrace( 141 fmt.Errorf("removing table %q failed: %w", pt, err), 142 ) 143 } 144 145 case scheme.EntryTopic: 146 err = db.Topic().Drop(ctx, pt) 147 if err != nil { 148 return xerrors.WithStackTrace( 149 fmt.Errorf("removing topic %q failed: %w", pt, err), 150 ) 151 } 152 153 default: 154 return xerrors.WithStackTrace( 155 fmt.Errorf("unknown entry type: %s", t.String()), 156 ) 157 } 158 } 159 160 if entry.Type != scheme.EntryDirectory { 161 return nil 162 } 163 164 err = db.Scheme().RemoveDirectory(ctx, p) 165 if err != nil { 166 return xerrors.WithStackTrace( 167 fmt.Errorf("removing directory %q failed: %w", p, err), 168 ) 169 } 170 171 return nil 172 } 173 if !strings.HasPrefix(pathToRemove, db.Name()) { 174 pathToRemove = path.Join(db.Name(), pathToRemove) 175 } 176 177 return rmPath(0, pathToRemove) 178 }