github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/sqle/remotesrv.go (about) 1 // Copyright 2022 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package sqle 16 17 import ( 18 "context" 19 20 "github.com/dolthub/go-mysql-server/sql" 21 22 "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" 23 "github.com/dolthub/dolt/go/libraries/doltcore/remotesrv" 24 "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess" 25 "github.com/dolthub/dolt/go/libraries/utils/filesys" 26 "github.com/dolthub/dolt/go/store/datas" 27 ) 28 29 type remotesrvStore struct { 30 ctxFactory func(context.Context) (*sql.Context, error) 31 createDBs bool 32 } 33 34 var _ remotesrv.DBCache = remotesrvStore{} 35 36 func (s remotesrvStore) Get(ctx context.Context, path, nbfVerStr string) (remotesrv.RemoteSrvStore, error) { 37 sqlCtx, err := s.ctxFactory(ctx) 38 if err != nil { 39 return nil, err 40 } 41 sess := dsess.DSessFromSess(sqlCtx.Session) 42 db, err := sess.Provider().Database(sqlCtx, path) 43 if err != nil { 44 if s.createDBs && sql.ErrDatabaseNotFound.Is(err) { 45 err = sess.Provider().CreateDatabase(sqlCtx, path) 46 if err != nil { 47 return nil, err 48 } 49 db, err = sess.Provider().Database(sqlCtx, path) 50 if err != nil { 51 return nil, err 52 } 53 } else { 54 return nil, err 55 } 56 } 57 58 sdb, ok := db.(dsess.SqlDatabase) 59 if !ok { 60 return nil, remotesrv.ErrUnimplemented 61 } 62 datasdb := doltdb.HackDatasDatabaseFromDoltDB(sdb.DbData().Ddb) 63 cs := datas.ChunkStoreFromDatabase(datasdb) 64 rss, ok := cs.(remotesrv.RemoteSrvStore) 65 if !ok { 66 return nil, remotesrv.ErrUnimplemented 67 } 68 return rss, nil 69 } 70 71 // In the SQL context, the database provider that we use to expose the 72 // remotesapi interface can choose to either create a newly accessed database 73 // on first access or to return NotFound. Currently we allow creation in the 74 // cluster replication context, where the replicated database should definitely 75 // be made to exist and the accesses are always writes, but we disallow it in 76 // the exposed-as-a-remotesapi-endpoint use case, where the requested database 77 // may just be a typo or a configuration mistake on the part of the user. 78 79 type CreateUnknownDatabasesSetting bool 80 81 const CreateUnknownDatabases CreateUnknownDatabasesSetting = true 82 const DoNotCreateUnknownDatabases CreateUnknownDatabasesSetting = false 83 84 // Considers |args| and returns a new |remotesrv.ServerArgs| instance which 85 // will serve databases accessible through |ctxFactory|. 86 func RemoteSrvFSAndDBCache(ctxFactory func(context.Context) (*sql.Context, error), createSetting CreateUnknownDatabasesSetting) (filesys.Filesys, remotesrv.DBCache, error) { 87 sqlCtx, err := ctxFactory(context.Background()) 88 if err != nil { 89 return nil, nil, err 90 } 91 sess := dsess.DSessFromSess(sqlCtx.Session) 92 fs := sess.Provider().FileSystem() 93 dbcache := remotesrvStore{ctxFactory, bool(createSetting)} 94 return fs, dbcache, nil 95 } 96 97 func WithUserPasswordAuth(args remotesrv.ServerArgs, authnz remotesrv.AccessControl) remotesrv.ServerArgs { 98 si := remotesrv.ServerInterceptor{ 99 Lgr: args.Logger, 100 AccessController: authnz, 101 } 102 args.Options = append(args.Options, si.Options()...) 103 return args 104 }