surrealpatch/db/db.go

204 lines
4.2 KiB
Go
Raw Normal View History

// 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 db
import (
"fmt"
"time"
"github.com/abcum/fibre"
"github.com/abcum/surreal/cnf"
2016-05-25 11:33:05 +00:00
"github.com/abcum/surreal/kvs"
"github.com/abcum/surreal/log"
"github.com/abcum/surreal/sql"
)
type Response struct {
2016-05-25 11:32:32 +00:00
Time string `json:"time,omitempty"`
Status interface{} `json:"status,omitempty"`
Detail interface{} `json:"detail,omitempty"`
Result interface{} `json:"result,omitempty"`
}
2016-05-25 11:33:05 +00:00
var db *kvs.DB
2016-07-04 10:37:29 +00:00
var quit chan int
var tick *time.Ticker
// Setup sets up the connection with the data layer
func Setup(opts *cnf.Options) (err error) {
2016-06-15 12:38:37 +00:00
log.WithPrefix("db").Infof("Starting database at %s", opts.DB.Path)
db, err = kvs.New(opts.DB.Path)
2016-07-04 10:37:29 +00:00
// backup(opts)
return
}
// Exit shuts down the connection with the data layer
func Exit() {
2016-06-15 12:38:37 +00:00
log.WithPrefix("db").Infof("Gracefully shutting down database")
2016-07-04 10:37:29 +00:00
// quit <- 0
2016-05-25 11:33:05 +00:00
db.Close()
}
func Prepare(sql string, param ...interface{}) string {
return fmt.Sprintf(sql, param...)
}
// Execute parses the query and executes it against the data layer
func Execute(ctx *fibre.Context, txt interface{}) (out []interface{}, err error) {
ast, err := sql.Parse(ctx, txt)
2016-02-27 12:05:35 +00:00
if err != nil {
return
}
chn := make(chan interface{})
go execute(ctx, ast, chn)
for res := range chn {
out = append(out, res)
2016-02-27 12:05:35 +00:00
}
return
}
2016-07-04 10:37:29 +00:00
func backup(opts *cnf.Options) {
/*tick = time.NewTicker(opts.Backups.Time)
quit = make(chan int)
go func() {
for {
select {
case <-tick.C:
t := time.Now().Format("2006-01-02T15-04-05")
n := fmt.Sprintf("%s.backup.db", t)
db.Save(n)
case <-quit:
tick.Stop()
return
}
}
}()*/
}
2016-05-25 11:32:32 +00:00
func status(e error) interface{} {
switch e.(type) {
default:
return "OK"
2016-06-15 12:38:37 +00:00
case error:
return "ERR"
2016-05-25 11:32:32 +00:00
case *kvs.DBError:
return "ERR_DB"
case *kvs.TXError:
return "ERR_DB"
case *kvs.CKError:
return "ERR_CK"
case *kvs.KVError:
return "ERR_EXISTS"
}
}
func detail(e error) interface{} {
2016-06-15 12:38:37 +00:00
switch err := e.(type) {
2016-05-25 11:32:32 +00:00
default:
return nil
2016-06-15 12:38:37 +00:00
case error:
return err.Error()
2016-05-25 11:32:32 +00:00
case *kvs.DBError:
return "A database error occured"
case *kvs.TXError:
return "A database error occured"
case *kvs.CKError:
return "A cipherkey error occured"
case *kvs.KVError:
return "The item already exists"
}
}
func execute(ctx *fibre.Context, ast *sql.Query, chn chan interface{}) {
2016-07-04 10:37:29 +00:00
defer close(chn)
2016-02-27 12:05:35 +00:00
for _, s := range ast.Statements {
var res []interface{}
var err error
now := time.Now()
switch stm := s.(type) {
case *sql.UseStatement:
continue
case *sql.SelectStatement:
res, err = executeSelectStatement(stm)
case *sql.CreateStatement:
res, err = executeCreateStatement(stm)
case *sql.UpdateStatement:
res, err = executeUpdateStatement(stm)
case *sql.ModifyStatement:
res, err = executeModifyStatement(stm)
case *sql.DeleteStatement:
res, err = executeDeleteStatement(stm)
case *sql.RelateStatement:
res, err = executeRelateStatement(stm)
case *sql.RecordStatement:
res, err = executeRecordStatement(stm)
2016-05-25 10:47:11 +00:00
case *sql.DefineTableStatement:
res, err = executeDefineTableStatement(stm)
case *sql.RemoveTableStatement:
res, err = executeRemoveTableStatement(stm)
case *sql.DefineFieldStatement:
res, err = executeDefineFieldStatement(stm)
case *sql.RemoveFieldStatement:
res, err = executeRemoveFieldStatement(stm)
case *sql.DefineIndexStatement:
res, err = executeDefineIndexStatement(stm)
case *sql.ResyncIndexStatement:
res, err = executeResyncIndexStatement(stm)
case *sql.RemoveIndexStatement:
res, err = executeRemoveIndexStatement(stm)
}
chn <- &Response{
Time: time.Since(now).String(),
2016-05-25 11:32:32 +00:00
Status: status(err),
Detail: detail(err),
Result: append([]interface{}{}, res...),
}
}
}