diff options
Diffstat (limited to 'system/db/query.go')
-rw-r--r-- | system/db/query.go | 156 |
1 files changed, 150 insertions, 6 deletions
diff --git a/system/db/query.go b/system/db/query.go index c9cf37c..06e9c62 100644 --- a/system/db/query.go +++ b/system/db/query.go @@ -1,17 +1,161 @@ package db +import ( + "bytes" + "encoding/json" + "fmt" + "log" + "net/url" + "strconv" + "strings" + + "github.com/boltdb/bolt" + "github.com/gorilla/schema" + "github.com/nilslice/cms/content" +) + +var store *bolt.DB + +func init() { + var err error + store, err = bolt.Open("store.db", 0666, nil) + if err != nil { + log.Fatal(err) + } +} + // Set inserts or updates values in the database. -// The `key` argument is a string made up of namespace:id (string:int) -func Set(key string) error { +// The `target` argument is a string made up of namespace:id (string:int) +func Set(target string, data url.Values) (int, error) { + t := strings.Split(target, ":") + ns, id := t[0], t[1] - return nil + // check if content has an id, and if not get new one from target bucket + if len(id) == 0 { + return insert(ns, data) + } + + return update(ns, id, data) +} + +func update(ns, id string, data url.Values) (int, error) { + cid, err := strconv.Atoi(id) + if err != nil { + return 0, err + } + + err = store.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucketIfNotExists([]byte(ns)) + if err != nil { + return err + } + + j, err := toJSON(ns, data) + if err != nil { + return err + } + + err = b.Put([]byte(fmt.Sprintf("%d", cid)), j) + if err != nil { + return err + } + + return nil + }) + if err != nil { + return 0, nil + } + + return cid, nil +} + +func insert(ns string, data url.Values) (int, error) { + var effectedID int + err := store.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucketIfNotExists([]byte(ns)) + if err != nil { + return err + } + + // get the next available ID and convert to string + // also set effectedID to int of ID + id, err := b.NextSequence() + if err != nil { + return err + } + cid := strconv.FormatUint(id, 10) + effectedID, err = strconv.Atoi(cid) + if err != nil { + return err + } + data.Add("id", cid) + + j, err := toJSON(ns, data) + if err != nil { + return err + } + + err = b.Put([]byte(cid), j) + if err != nil { + return err + } + + return nil + }) + if err != nil { + return 0, err + } + + return effectedID, nil +} + +func toJSON(ns string, data url.Values) ([]byte, error) { + // find the content type and decode values into it + t, ok := content.Types[ns] + if !ok { + return nil, fmt.Errorf(content.ErrTypeNotRegistered, ns) + } + post := t() + + dec := schema.NewDecoder() + dec.SetAliasTag("json") // allows simpler struct tagging when creating a content type + dec.IgnoreUnknownKeys(true) // will skip over form values submitted, but not in struct + err := dec.Decode(post, data) + if err != nil { + return nil, err + } + + // marshall content struct to json for db storage + j, err := json.Marshal(post) + if err != nil { + return nil, err + } + + return j, nil } // Get retrives one item from the database. Non-existent values will return an empty []byte -// The `key` argument is a string made up of namespace:id (string:int) -func Get(key string) []byte { +// The `target` argument is a string made up of namespace:id (string:int) +func Get(target string) ([]byte, error) { + t := strings.Split(target, ":") + ns, id := t[0], t[1] - return nil + val := &bytes.Buffer{} + err := store.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte(ns)) + _, err := val.Write(b.Get([]byte(id))) + if err != nil { + fmt.Println(err) + return err + } + + return nil + }) + if err != nil { + return nil, err + } + + return val.Bytes(), nil } // GetAll retrives all items from the database within the provided namespace |