diff --git a/cli/setup.go b/cli/setup.go index 9fa5d26a..6548da5b 100644 --- a/cli/setup.go +++ b/cli/setup.go @@ -56,7 +56,7 @@ func setup() { } if opts.DB.Path != "memory" { - if ok, _ := regexp.MatchString(`^(s3|gcs|logr|file|rixxdb|dendrodb)://(.+)$`, opts.DB.Path); !ok { + if ok, _ := regexp.MatchString(`^(s3|gcs|logr|file|mysql|rixxdb|dendrodb)://(.+)$`, opts.DB.Path); !ok { log.Fatalf("Invalid path %s. Specify a valid data store configuration path", opts.DB.Path) } } diff --git a/db/db.go b/db/db.go index 83e1121b..379fe8bf 100644 --- a/db/db.go +++ b/db/db.go @@ -32,6 +32,7 @@ import ( "cloud.google.com/go/trace" + _ "github.com/abcum/surreal/kvs/mysql" _ "github.com/abcum/surreal/kvs/rixxdb" ) diff --git a/kvs/ds.go b/kvs/ds.go index 81a8923f..47bf7ab3 100644 --- a/kvs/ds.go +++ b/kvs/ds.go @@ -45,6 +45,8 @@ func New(opts *cnf.Options) (ds *DS, err error) { db, err = stores["rixxdb"](opts) case strings.HasPrefix(opts.DB.Path, "file://"): db, err = stores["rixxdb"](opts) + case strings.HasPrefix(opts.DB.Path, "mysql://"): + db, err = stores["mysql"](opts) case strings.HasPrefix(opts.DB.Path, "rixxdb://"): db, err = stores["rixxdb"](opts) case strings.HasPrefix(opts.DB.Path, "dendrodb://"): diff --git a/kvs/mysql/db.go b/kvs/mysql/db.go new file mode 100644 index 00000000..f09f37f5 --- /dev/null +++ b/kvs/mysql/db.go @@ -0,0 +1,57 @@ +// Copyright © 2016 Abcum Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mysql + +import ( + "io" + + "context" + + "database/sql" + + "github.com/abcum/surreal/kvs" +) + +type DB struct { + pntr *sql.DB +} + +func (db *DB) Begin(ctx context.Context, writable bool) (txn kvs.TX, err error) { + var pntr *sql.Tx + if pntr, err = db.pntr.BeginTx(ctx, db.opt(writable)); err != nil { + err = &kvs.DBError{Err: err} + return + } + return &TX{pntr: pntr}, err +} + +func (db *DB) Import(r io.Reader) (err error) { + return nil +} + +func (db *DB) Export(w io.Writer) (err error) { + return nil +} + +func (db *DB) Close() (err error) { + return db.pntr.Close() +} + +func (db *DB) opt(writable bool) *sql.TxOptions { + return &sql.TxOptions{ + ReadOnly: !writable, + Isolation: sql.LevelReadCommitted, + } +} diff --git a/kvs/mysql/kv.go b/kvs/mysql/kv.go new file mode 100644 index 00000000..e5bebc0d --- /dev/null +++ b/kvs/mysql/kv.go @@ -0,0 +1,42 @@ +// Copyright © 2016 Abcum Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mysql + +// KV represents a row stored in the database. +type KV struct { + ver uint64 + key []byte + val []byte +} + +// Exi returns whether this key-value item actually exists. +func (kv *KV) Exi() bool { + return kv.val != nil +} + +// Key returns the key for the underlying key-value item. +func (kv *KV) Key() []byte { + return kv.key +} + +// Val returns the value for the underlying key-value item. +func (kv *KV) Val() []byte { + return kv.val +} + +// Ver returns the version for the underlying key-value item. +func (kv *KV) Ver() uint64 { + return kv.ver +} diff --git a/kvs/mysql/main.go b/kvs/mysql/main.go new file mode 100644 index 00000000..32c5abaf --- /dev/null +++ b/kvs/mysql/main.go @@ -0,0 +1,49 @@ +// Copyright © 2016 Abcum Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mysql + +import ( + "strings" + + "database/sql" + + "github.com/abcum/surreal/cnf" + "github.com/abcum/surreal/kvs" + + "github.com/go-sql-driver/mysql" + + "github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/proxy" +) + +func init() { + + mysql.RegisterDial("cloudsql", proxy.Dial) + + kvs.Register("mysql", func(opts *cnf.Options) (db kvs.DB, err error) { + + var pntr *sql.DB + + path := strings.TrimPrefix(opts.DB.Path, "mysql://") + + pntr, err = sql.Open("mysql", path) + if err != nil { + return + } + + return &DB{pntr: pntr}, err + + }) + +} diff --git a/kvs/mysql/sql.go b/kvs/mysql/sql.go new file mode 100644 index 00000000..36a04e65 --- /dev/null +++ b/kvs/mysql/sql.go @@ -0,0 +1,130 @@ +// Copyright © 2016 Abcum Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mysql + +const sqlClr = ` + DELETE FROM kv + WHERE k=? +` + +const sqlClrP = ` + DELETE FROM kv + WHERE k LIKE CONCAT(?, '%') + LIMIT ? +` + +const sqlClrR = ` + DELETE FROM kv + WHERE k>=? AND k=? AND k=? AND k m { + continue + } + b[i] = chars[c%t] + i++ + if i == l { + return b + } + } + + } + +}