summaryrefslogtreecommitdiff
path: root/system/db/query.go
diff options
context:
space:
mode:
Diffstat (limited to 'system/db/query.go')
-rw-r--r--system/db/query.go156
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