项目作者: datatogether

项目描述 :
Experimental Golang implementation of the ipfs datastore interface for sql databases.
高级语言: Go
项目地址: git://github.com/datatogether/sql_datastore.git
创建时间: 2017-06-10T23:13:41Z
项目社区:https://github.com/datatogether/sql_datastore

开源协议:GNU Affero General Public License v3.0

下载


sql_datastore


import “github.com/datatogether/sql_datastore”

sql_datastore is an experimental implementation of the ipfs datastore interface
for sql databases. It’s very much a work in progress, born out of a somewhat
special use case of needing to be able to store data in a number of different
places, with the datastore interface as a lowest-common-denominator.

The goal is not a fully-expressive sql database operated through the datastore
interface, this is not possible, or even desired. Instead, this package focuses
on doing the kinds of things one would want to do with a key-value datastore,
requiring implementers to provide a standard set of queries and parameters to
glue everything together. Whenever the datastore interface is not expressive
enough, one can always fall back to standard SQL work.

sql_datastore reconciles the key-value orientation of the datastore interface
with the tables/relational orientation of SQL databases through the concept of a
“Model”. Model is a bit of an unfortunate name, as it implies this package is an
ORM, which isn’t a design goal.

Annnnnnnnyway, the important patterns of this approach are:

  1. 1. The Model interface defines how to get stuff into and out of SQL
  2. 2. All Models that will be interacted with must be "Registered" to the store.
  3. Registered Models map to a datastore.Key Type.
  4. 3. All Get/Put/Delete/Has/Query to sql_datastore must map to a single Model

This implementation leads to a great deal of required boilerplate code to
implement. In the future this package could be expanded to become syntax-aware,
accepting a table name & schema definition for registered models. From here the
sql_datastore package could construct default queries that could be overridden
using the current SQLQuery & SQLParams methods. Before that happens, it’s worth
noting that the datastore interface may undergo changes in the near future.

Usage

  1. var DefaultStore = NewDatastore(nil)

Package Level Datastore. Be sure to call SetDB before using!

func Register

  1. func Register(models ...Model) error

Register a number of models to the DefaultStore

func SetDB

  1. func SetDB(db *sql.DB)

SetDB sets the DefaultStore’s DB, must be called for DefaultStore to work

type Cmd

  1. type Cmd int

Cmd represents a set of standardized SQL queries these abstractions define a
common set of commands that a model can provide to sql_datastore for execution.

  1. const (
  2. // Unknown as default, errored state. CmdUnknown should never
  3. // be intentionally passed to... anything.
  4. CmdUnknown Cmd = iota
  5. // starting with DDL statements:
  6. // CREATE TABLE query
  7. CmdCreateTable
  8. // ALTER TABLE statement
  9. CmdAlterTable
  10. // DROP TABLE statement
  11. CmdDropTable
  12. // SELECT statement that should return a single result
  13. CmdSelectOne
  14. // INSERT a single row
  15. CmdInsertOne
  16. // UPDATE a single row
  17. CmdUpdateOne
  18. // DELETE a single row
  19. CmdDeleteOne
  20. // Check if a single row exists
  21. CmdExistsOne
  22. // List Query, can return many rows. List is special
  23. // in that LIMIT & OFFSET params are provided by the query
  24. // method. See note in Datastore.Query()
  25. CmdList
  26. )

type Datastore

  1. type Datastore struct {
  2. // DB is the underlying DB handler
  3. // it should be safe for use outside of the
  4. // Datastore itself
  5. DB *sql.DB
  6. }

Datastore implements the ipfs datastore interface for SQL databases

func NewDatastore

  1. func NewDatastore(db *sql.DB) *Datastore

NewDatastore creates a datastore instance Datastores should be pointers.

func (*Datastore) Batch

  1. func (ds *Datastore) Batch() (datastore.Batch, error)

Batch commands are currently not supported

func (Datastore) Delete

  1. func (ds Datastore) Delete(key datastore.Key) error

Delete a value from the store

func (Datastore) Get

  1. func (ds Datastore) Get(key datastore.Key) (value interface{}, err error)

Get a model from the store

func (Datastore) Has

  1. func (ds Datastore) Has(key datastore.Key) (exists bool, err error)

Check to see if key exists in the db

func (Datastore) Put

  1. func (ds Datastore) Put(key datastore.Key, value interface{}) error

Put a model in the store

func (Datastore) Query

  1. func (ds Datastore) Query(q query.Query) (query.Results, error)

Ok, this is nothing more than a first step. In the future it seems datastore
will need to construct these queries, which will require more info (tablename,
expected response schema) from the model. Currently it’s required that the
passed-in prefix be equal to DatastoreType() which query will use to determine
what model to ask for a ListCmd

func (*Datastore) Register

  1. func (ds *Datastore) Register(models ...Model) error

Register one or more models that will be used by this datastore. Must be called
before a model can be manipulated by the store

type FilterKeyTypeEq

  1. type FilterKeyTypeEq string

FilterTypeEq filters for a specific key Type (which should match a registerd
model on the sql_datastore.Datastore) FilterTypeEq is a string that specifies
the key type we’re after

func (FilterKeyTypeEq) Filter

  1. func (f FilterKeyTypeEq) Filter(e query.Entry) bool

Filter satisfies the query.Filter interface TODO - make this work properly for
the sake of other datastores

func (FilterKeyTypeEq) Key

  1. func (f FilterKeyTypeEq) Key() datastore.Key

Key return s FilterKeyTypeEq formatted as a datastore.Key

func (FilterKeyTypeEq) String

  1. func (f FilterKeyTypeEq) String() string

Satisfy the Stringer interface

type Model

  1. type Model interface {
  2. // DatastoreType must return the "type" of object, which is a consistent
  3. // name for the object being stored. DatastoreType works in conjunction
  4. // with GetId to construct the key for storage.
  5. DatastoreType() string
  6. // GetId should return the standalone cannonical ID for the object.
  7. GetId() string
  8. // Key is a methoda that traditionally combines DatastoreType() and GetId()
  9. // to form a key that can be provided to Get & Has commands
  10. // eg:
  11. // func (m) Key() datastore.Key {
  12. // return datastore.NewKey(fmt.Sprintf("%s:%s", m.DatastoreType(), m.GetId()))
  13. // }
  14. // in examples of "submodels" of another model it makes sense to leverage the
  15. // POSIX structure of keys. for example:
  16. // func (m) Key() datastore.Key {
  17. // return datastore.NewKey(fmt.Sprintf("%s:%s/%s", m.DatastoreType(), m.ParentId(), m.GetId()))
  18. // }
  19. Key() datastore.Key
  20. // NewSQLModel must allocate & return a new instance of the
  21. // model with id set such that GetId returns the passed-in Key
  22. // NewSQLModel will be passed keys for creation of new blank models
  23. NewSQLModel(key datastore.Key) Model
  24. // SQLQuery gives the datastore the query to execute for a given command type
  25. // As an example, if CmdSelectOne is passed in, something like
  26. // "SELECT * FROM table WHERE id = $1"
  27. // should be returned
  28. SQLQuery(Cmd) string
  29. // SQLParams gives the datastore the required params for a given command type
  30. // As an example if CmdSelectOne is passed in, something like
  31. // []interface{}{m.id}
  32. // should be returned.
  33. SQLParams(Cmd) []interface{}
  34. // UnmarshalSQL takes it's que from UnmarshalJSON, with the difference that
  35. // the result of Unmarshaling should be assigned to the receiver.
  36. UnmarshalSQL(sqlutil.Scannable) error
  37. }

Model is the interface that must be implemented to work with sql_datastore.
There are some fairly heavy constraints here. For a working example checkout:
https://github.com/archivers-space/archive and have a look at primer.go

type OrderBy

  1. type OrderBy string

Order a query by a field

func (OrderBy) Sort

  1. func (o OrderBy) Sort([]query.Entry)

satisfy datastore.Order interface, this is a no-op b/c sql sorting will happen
at query-time TODO - In the future this should be generalized to facilitate
supplying sql_datastore.OrderBy orders to other datastores, providing parity

func (OrderBy) String

  1. func (o OrderBy) String() string

String value, used to inject the field name istself as a SQL query param

type OrderByDesc

  1. type OrderByDesc string

Order a query by a field, descending

func (OrderByDesc) Sort

  1. func (o OrderByDesc) Sort([]query.Entry)

satisfy datastore.Order interface, this is a no-op b/c sql sorting will happen
at query-time TODO - In the future this should be generalized to facilitate
supplying sql_datastore.OrderBy orders to other datastores, providing parity

func (OrderByDesc) String

  1. func (o OrderByDesc) String() string

String value, used to inject the field name istself as a SQL query param