-
Notifications
You must be signed in to change notification settings - Fork 5
/
driver.go
137 lines (115 loc) · 3.72 KB
/
driver.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package embedded
import (
"context"
"database/sql"
"database/sql/driver"
"fmt"
"github.com/dolthub/dolt/go/cmd/dolt/commands/engine"
"github.com/dolthub/dolt/go/cmd/dolt/errhand"
"github.com/dolthub/dolt/go/libraries/doltcore/env"
"github.com/dolthub/dolt/go/libraries/utils/config"
"github.com/dolthub/dolt/go/libraries/utils/filesys"
gmssql "github.com/dolthub/go-mysql-server/sql"
"github.com/dolthub/vitess/go/mysql"
)
const (
DoltDriverName = "dolt"
CommitNameParam = "commitname"
CommitEmailParam = "commitemail"
DatabaseParam = "database"
MultiStatementsParam = "multistatements"
ClientFoundRowsParam = "clientfoundrows"
)
var _ driver.Driver = (*doltDriver)(nil)
func init() {
sql.Register(DoltDriverName, &doltDriver{})
}
// doltDriver is a driver.Driver implementation which provides access to a dolt database on the local filesystem
type doltDriver struct {
}
// Open opens and returns a connection to the datasource referenced by the string provided using the options provided.
// datasources must be in file url format:
//
// file:///User/brian/driver/example/path?commitname=Billy%20Bob&[email protected]&database=dbname
//
// The path needs to point to a directory whose subdirectories are dolt databases. If a "Create Database" command is
// run a new subdirectory will be created in this path.
// The supported parameters are
func (d *doltDriver) Open(dataSource string) (driver.Conn, error) {
ctx := context.Background()
var fs filesys.Filesys = filesys.LocalFS
ds, err := ParseDataSource(dataSource)
if err != nil {
return nil, err
}
exists, isDir := fs.Exists(ds.Directory)
if !exists {
return nil, fmt.Errorf("'%s' does not exist", ds.Directory)
} else if !isDir {
return nil, fmt.Errorf("%s: is a file. Need to specify a directory", ds.Directory)
}
fs, err = fs.WithWorkingDir(ds.Directory)
if err != nil {
return nil, err
}
name := ds.Params[CommitNameParam]
if name == nil {
return nil, fmt.Errorf("datasource '%s' must include the parameter '%s'", dataSource, CommitNameParam)
}
email := ds.Params[CommitEmailParam]
if email == nil {
return nil, fmt.Errorf("datasource '%s' must include the parameter '%s'", dataSource, CommitEmailParam)
}
cfg := config.NewMapConfig(map[string]string{
config.UserNameKey: name[0],
config.UserEmailKey: email[0],
})
mrEnv, err := LoadMultiEnvFromDir(ctx, cfg, fs, ds.Directory, "0.40.17")
if err != nil {
return nil, err
}
seCfg := &engine.SqlEngineConfig{
IsReadOnly: false,
ServerUser: "root",
Autocommit: true,
}
se, err := engine.NewSqlEngine(ctx, mrEnv, seCfg)
if err != nil {
return nil, err
}
gmsCtx, err := se.NewLocalContext(ctx)
if err != nil {
return nil, err
}
if database, ok := ds.Params[DatabaseParam]; ok && len(database) == 1 {
gmsCtx.SetCurrentDatabase(database[0])
}
if ds.ParamIsTrue(ClientFoundRowsParam) {
client := gmsCtx.Client()
gmsCtx.SetClient(gmssql.Client{
User: client.User,
Address: client.Address,
Capabilities: client.Capabilities | mysql.CapabilityClientFoundRows,
})
}
return &DoltConn{
DataSource: ds,
se: se,
gmsCtx: gmsCtx,
}, nil
}
// LoadMultiEnvFromDir looks at each subfolder of the given path as a Dolt repository and attempts to return a MultiRepoEnv
// with initialized environments for each of those subfolder data repositories. subfolders whose name starts with '.' are
// skipped.
func LoadMultiEnvFromDir(
ctx context.Context,
cfg config.ReadWriteConfig,
fs filesys.Filesys,
path, version string,
) (*env.MultiRepoEnv, error) {
multiDbDirFs, err := fs.WithWorkingDir(path)
if err != nil {
return nil, errhand.VerboseErrorFromError(err)
}
return env.MultiEnvForDirectory(ctx, cfg, multiDbDirFs, version, nil)
}