Skip to content
This repository has been archived by the owner on Nov 7, 2019. It is now read-only.

Collection tables #16

Merged
merged 6 commits into from
Aug 5, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 3 additions & 40 deletions collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package archive

import (
"database/sql"
"encoding/json"
"fmt"
"github.com/datatogether/sql_datastore"
"github.com/datatogether/sqlutil"
Expand Down Expand Up @@ -30,10 +29,6 @@ type Collection struct {
Description string `json:"description"`
// url this collection originates from
Url string `json:"url,omitempty"`
// csv column headers, first value must always be "hash"
Schema []string `json:"schema,omitempty"`
// actuall collection contents
Contents [][]string `json:"contents,omitempty"`
}

func (c Collection) DatastoreType() string {
Expand Down Expand Up @@ -90,9 +85,9 @@ func (c *Collection) Delete(store datastore.Datastore) error {
return store.Delete(c.Key())
}

func (c *Collection) NewSQLModel(id string) sql_datastore.Model {
func (c *Collection) NewSQLModel(key datastore.Key) sql_datastore.Model {
return &Collection{
Id: id,
Id: key.Name(),
}
}

Expand Down Expand Up @@ -124,15 +119,6 @@ func (c *Collection) SQLParams(cmd sql_datastore.Cmd) []interface{} {
case sql_datastore.CmdList:
return nil
default:
schemaBytes, err := json.Marshal(c.Schema)
if err != nil {
panic(err)
}
contentBytes, err := json.Marshal(c.Contents)
if err != nil {
panic(err)
}

return []interface{}{
c.Id,
c.Created.In(time.UTC),
Expand All @@ -141,8 +127,6 @@ func (c *Collection) SQLParams(cmd sql_datastore.Cmd) []interface{} {
c.Title,
c.Description,
c.Url,
schemaBytes,
contentBytes,
}
}
}
Expand All @@ -153,34 +137,15 @@ func (c *Collection) UnmarshalSQL(row sqlutil.Scannable) (err error) {
var (
id, creator, title, description, url string
created, updated time.Time
schemaBytes, contentBytes []byte
)

if err := row.Scan(&id, &created, &updated, &creator, &title, &description, &url, &schemaBytes, &contentBytes); err != nil {
if err := row.Scan(&id, &created, &updated, &creator, &title, &description, &url); err != nil {
if err == sql.ErrNoRows {
return ErrNotFound
}
return err
}

var schema []string
if schemaBytes != nil {
schema = []string{}
err = json.Unmarshal(schemaBytes, &schema)
if err != nil {
return err
}
}

var contents [][]string
if contentBytes != nil {
contents = [][]string{}
err = json.Unmarshal(contentBytes, &contents)
if err != nil {
return err
}
}

*c = Collection{
Id: id,
Created: created.In(time.UTC),
Expand All @@ -189,8 +154,6 @@ func (c *Collection) UnmarshalSQL(row sqlutil.Scannable) (err error) {
Title: title,
Description: description,
Url: url,
Schema: schema,
Contents: contents,
}

return nil
Expand Down
166 changes: 166 additions & 0 deletions collection_item.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package archive

import (
"database/sql"
"fmt"
"github.com/datatogether/sql_datastore"
"github.com/datatogether/sqlutil"
"github.com/ipfs/go-datastore"
)

// CollectionItem is an item in a collection. They are urls
// with added collection-specific information.
// This has the effect of storing all of the "main properties"
// of a collection item in the common list of urls
type CollectionItem struct {
// Collection Items are Url's at heart
Url
// need a reference to the collection Id to be set to distinguish
// this item's membership in this particular list
collectionId string
// this item's index in the collection
Index int `json:"index"`
// unique description of this item
Description string `json:"description"`
}

// DatastoreType is to satisfy sql_datastore.Model interface
func (c CollectionItem) DatastoreType() string {
return "CollectionItem"
}

// GetId returns the Id of the collectionItem, which is the id
// of the underlying Url
func (c CollectionItem) GetId() string {
return c.Url.Id
}

// Key is somewhat special as CollectionItems always have a Collection
// as their parent. This relationship is represented in directory-form:
// /Collection:[collection-id]/CollectionItem:[item-id]
func (c CollectionItem) Key() datastore.Key {
return datastore.NewKey(fmt.Sprintf("%s:%s/%s:%s", Collection{}.DatastoreType(), c.collectionId, c.DatastoreType(), c.GetId()))
}

// Read collection from db
func (c *CollectionItem) Read(store datastore.Datastore) error {
if c.Url.Id == "" && c.Url.Url != "" {
if sqls, ok := store.(*sql_datastore.Datastore); ok {
row := sqls.DB.QueryRow(qUrlByUrlString, c.Url.Url)
prev := &Url{}
if err := prev.UnmarshalSQL(row); err == nil {
c.Id = prev.Id
// exists = true
}
}
}

ci, err := store.Get(c.Key())
if err != nil {
return err
}

got, ok := ci.(*CollectionItem)
if !ok {
return ErrInvalidResponse
}
*c = *got
return nil
}

// Save a collection item to a store
func (c *CollectionItem) Save(store datastore.Datastore) (err error) {
u := &c.Url
if err := u.Save(store); err != nil {
return err
}

c.Url = *u
return store.Put(c.Key(), c)
}

// Delete a collection item
func (c *CollectionItem) Delete(store datastore.Datastore) error {
return store.Delete(c.Key())
}

func (c *CollectionItem) NewSQLModel(key datastore.Key) sql_datastore.Model {
l := key.List()
if len(l) == 1 {
return &CollectionItem{
collectionId: datastore.NamespaceValue(l[0]),
}
} else if len(l) == 2 {
return &CollectionItem{
collectionId: datastore.NamespaceValue(l[0]),
Url: Url{Id: datastore.NamespaceValue(l[1])},
}
}
return &CollectionItem{}
}

// SQLQuery is to satisfy the sql_datastore.Model interface, it
// returns the concrete query for a given type of SQL command
func (c CollectionItem) SQLQuery(cmd sql_datastore.Cmd) string {
switch cmd {
case sql_datastore.CmdCreateTable:
return qCollectionItemCreateTable
case sql_datastore.CmdExistsOne:
return qCollectionItemExists
case sql_datastore.CmdSelectOne:
return qCollectionItemById
case sql_datastore.CmdInsertOne:
return qCollectionItemInsert
case sql_datastore.CmdUpdateOne:
return qCollectionItemUpdate
case sql_datastore.CmdDeleteOne:
return qCollectionItemDelete
case sql_datastore.CmdList:
return qCollectionItems
default:
return ""
}
}

// SQLQuery is to satisfy the sql_datastore.Model interface, it
// returns this CollectionItem's parameters for a given type of SQL command
func (c *CollectionItem) SQLParams(cmd sql_datastore.Cmd) []interface{} {
switch cmd {
case sql_datastore.CmdSelectOne, sql_datastore.CmdExistsOne, sql_datastore.CmdDeleteOne:
return []interface{}{c.collectionId, c.Url.Id}
case sql_datastore.CmdList:
return []interface{}{c.collectionId}
default:
return []interface{}{
c.collectionId,
c.Url.Id,
c.Index,
c.Description,
}
}
}

// UnmarshalSQL reads an sql response into the collection receiver
// it expects the request to have used collectionCols() for selection
func (c *CollectionItem) UnmarshalSQL(row sqlutil.Scannable) (err error) {
var (
collectionId, urlId, url, hash, title, description string
index int
)

if err := row.Scan(&collectionId, &urlId, &hash, &url, &title, &index, &description); err != nil {
if err == sql.ErrNoRows {
return ErrNotFound
}
return err
}

*c = CollectionItem{
collectionId: collectionId,
Url: Url{Id: urlId, Hash: hash, Url: url, Title: title},
Index: index,
Description: description,
}

return nil
}
Loading