{"id":15285718,"url":"https://github.com/datatogether/sql_datastore","last_synced_at":"2025-10-07T01:30:19.235Z","repository":{"id":57487812,"uuid":"93970319","full_name":"datatogether/sql_datastore","owner":"datatogether","description":"Experimental Golang implementation of the ipfs datastore interface for sql databases.","archived":true,"fork":false,"pushed_at":"2017-11-04T16:10:02.000Z","size":34,"stargazers_count":4,"open_issues_count":3,"forks_count":1,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-10-01T15:07:18.544Z","etag":null,"topics":["datastore-interface","golang","ipfs","package","sql"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/datatogether.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-06-10T23:13:41.000Z","updated_at":"2023-01-28T16:43:22.000Z","dependencies_parsed_at":"2022-08-29T11:21:32.641Z","dependency_job_id":null,"html_url":"https://github.com/datatogether/sql_datastore","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datatogether%2Fsql_datastore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datatogether%2Fsql_datastore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datatogether%2Fsql_datastore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datatogether%2Fsql_datastore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/datatogether","download_url":"https://codeload.github.com/datatogether/sql_datastore/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235569500,"owners_count":19011184,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["datastore-interface","golang","ipfs","package","sql"],"created_at":"2024-09-30T15:07:17.362Z","updated_at":"2025-10-07T01:30:18.941Z","avatar_url":"https://github.com/datatogether.png","language":"Go","readme":"# sql_datastore\n--\n    import \"github.com/datatogether/sql_datastore\"\n\nsql_datastore is an experimental implementation of the ipfs datastore interface\nfor sql databases. It's very much a work in progress, born out of a somewhat\nspecial use case of needing to be able to store data in a number of different\nplaces, with the datastore interface as a lowest-common-denominator.\n\nThe goal is not a fully-expressive sql database operated through the datastore\ninterface, this is not possible, or even desired. Instead, this package focuses\non doing the kinds of things one would want to do with a key-value datastore,\nrequiring implementers to provide a standard set of queries and parameters to\nglue everything together. Whenever the datastore interface is not expressive\nenough, one can always fall back to standard SQL work.\n\nsql_datastore reconciles the key-value orientation of the datastore interface\nwith the tables/relational orientation of SQL databases through the concept of a\n\"Model\". Model is a bit of an unfortunate name, as it implies this package is an\nORM, which isn't a design goal.\n\nAnnnnnnnnyway, the important patterns of this approach are:\n\n    1. The Model interface defines how to get stuff into and out of SQL\n    2. All Models that will be interacted with must be \"Registered\" to the store.\n       Registered Models map to a datastore.Key Type.\n    3. All Get/Put/Delete/Has/Query to sql_datastore must map to a single Model\n\nThis implementation leads to a great deal of required boilerplate code to\nimplement. In the future this package could be expanded to become syntax-aware,\naccepting a table name \u0026 schema definition for registered models. From here the\nsql_datastore package could construct default queries that could be overridden\nusing the current SQLQuery \u0026 SQLParams methods. Before that happens, it's worth\nnoting that the datastore interface may undergo changes in the near future.\n\n## Usage\n\n```go\nvar DefaultStore = NewDatastore(nil)\n```\nPackage Level Datastore. Be sure to call SetDB before using!\n\n#### func  Register\n\n```go\nfunc Register(models ...Model) error\n```\nRegister a number of models to the DefaultStore\n\n#### func  SetDB\n\n```go\nfunc SetDB(db *sql.DB)\n```\nSetDB sets the DefaultStore's DB, must be called for DefaultStore to work\n\n#### type Cmd\n\n```go\ntype Cmd int\n```\n\nCmd represents a set of standardized SQL queries these abstractions define a\ncommon set of commands that a model can provide to sql_datastore for execution.\n\n```go\nconst (\n\t// Unknown as default, errored state. CmdUnknown should never\n\t// be intentionally passed to... anything.\n\tCmdUnknown Cmd = iota\n\t// starting with DDL statements:\n\t// CREATE TABLE query\n\tCmdCreateTable\n\t// ALTER TABLE statement\n\tCmdAlterTable\n\t// DROP TABLE statement\n\tCmdDropTable\n\t// SELECT statement that should return a single result\n\tCmdSelectOne\n\t// INSERT a single row\n\tCmdInsertOne\n\t// UPDATE a single row\n\tCmdUpdateOne\n\t// DELETE a single row\n\tCmdDeleteOne\n\t// Check if a single row exists\n\tCmdExistsOne\n\t// List Query, can return many rows. List is special\n\t// in that LIMIT \u0026 OFFSET params are provided by the query\n\t// method. See note in Datastore.Query()\n\tCmdList\n)\n```\n\n#### type Datastore\n\n```go\ntype Datastore struct {\n\t// DB is the underlying DB handler\n\t// it should be safe for use outside of the\n\t// Datastore itself\n\tDB *sql.DB\n}\n```\n\nDatastore implements the ipfs datastore interface for SQL databases\n\n#### func  NewDatastore\n\n```go\nfunc NewDatastore(db *sql.DB) *Datastore\n```\nNewDatastore creates a datastore instance Datastores should be pointers.\n\n#### func (*Datastore) Batch\n\n```go\nfunc (ds *Datastore) Batch() (datastore.Batch, error)\n```\nBatch commands are currently not supported\n\n#### func (Datastore) Delete\n\n```go\nfunc (ds Datastore) Delete(key datastore.Key) error\n```\nDelete a value from the store\n\n#### func (Datastore) Get\n\n```go\nfunc (ds Datastore) Get(key datastore.Key) (value interface{}, err error)\n```\nGet a model from the store\n\n#### func (Datastore) Has\n\n```go\nfunc (ds Datastore) Has(key datastore.Key) (exists bool, err error)\n```\nCheck to see if key exists in the db\n\n#### func (Datastore) Put\n\n```go\nfunc (ds Datastore) Put(key datastore.Key, value interface{}) error\n```\nPut a model in the store\n\n#### func (Datastore) Query\n\n```go\nfunc (ds Datastore) Query(q query.Query) (query.Results, error)\n```\nOk, this is nothing more than a first step. In the future it seems datastore\nwill need to construct these queries, which will require more info (tablename,\nexpected response schema) from the model. Currently it's required that the\npassed-in prefix be equal to DatastoreType() which query will use to determine\nwhat model to ask for a ListCmd\n\n#### func (*Datastore) Register\n\n```go\nfunc (ds *Datastore) Register(models ...Model) error\n```\nRegister one or more models that will be used by this datastore. Must be called\nbefore a model can be manipulated by the store\n\n#### type FilterKeyTypeEq\n\n```go\ntype FilterKeyTypeEq string\n```\n\nFilterTypeEq filters for a specific key Type (which should match a registerd\nmodel on the sql_datastore.Datastore) FilterTypeEq is a string that specifies\nthe key type we're after\n\n#### func (FilterKeyTypeEq) Filter\n\n```go\nfunc (f FilterKeyTypeEq) Filter(e query.Entry) bool\n```\nFilter satisfies the query.Filter interface TODO - make this work properly for\nthe sake of other datastores\n\n#### func (FilterKeyTypeEq) Key\n\n```go\nfunc (f FilterKeyTypeEq) Key() datastore.Key\n```\nKey return s FilterKeyTypeEq formatted as a datastore.Key\n\n#### func (FilterKeyTypeEq) String\n\n```go\nfunc (f FilterKeyTypeEq) String() string\n```\nSatisfy the Stringer interface\n\n#### type Model\n\n```go\ntype Model interface {\n\t// DatastoreType must return the \"type\" of object, which is a consistent\n\t// name for the object being stored. DatastoreType works in conjunction\n\t// with GetId to construct the key for storage.\n\tDatastoreType() string\n\t// GetId should return the standalone cannonical ID for the object.\n\tGetId() string\n\n\t// Key is a methoda that traditionally combines DatastoreType() and GetId()\n\t// to form a key that can be provided to Get \u0026 Has commands\n\t// eg:\n\t// func (m) Key() datastore.Key {\n\t// \treturn datastore.NewKey(fmt.Sprintf(\"%s:%s\", m.DatastoreType(), m.GetId()))\n\t// }\n\t// in examples of \"submodels\" of another model it makes sense to leverage the\n\t// POSIX structure of keys. for example:\n\t// func (m) Key() datastore.Key {\n\t// \treturn datastore.NewKey(fmt.Sprintf(\"%s:%s/%s\", m.DatastoreType(), m.ParentId(), m.GetId()))\n\t// }\n\tKey() datastore.Key\n\n\t// NewSQLModel must allocate \u0026 return a new instance of the\n\t// model with id set such that GetId returns the passed-in Key\n\t// NewSQLModel will be passed keys for creation of new blank models\n\tNewSQLModel(key datastore.Key) Model\n\n\t// SQLQuery gives the datastore the query to execute for a given command type\n\t// As an example, if CmdSelectOne is passed in, something like\n\t// \"SELECT * FROM table WHERE id = $1\"\n\t// should be returned\n\tSQLQuery(Cmd) string\n\t// SQLParams gives the datastore the required params for a given command type\n\t// As an example if CmdSelectOne is passed in, something like\n\t// []interface{}{m.id}\n\t// should be returned.\n\tSQLParams(Cmd) []interface{}\n\t// UnmarshalSQL takes it's que from UnmarshalJSON, with the difference that\n\t// the result of Unmarshaling should be assigned to the receiver.\n\tUnmarshalSQL(sqlutil.Scannable) error\n}\n```\n\nModel is the interface that must be implemented to work with sql_datastore.\nThere are some fairly heavy constraints here. For a working example checkout:\nhttps://github.com/archivers-space/archive and have a look at primer.go\n\n#### type OrderBy\n\n```go\ntype OrderBy string\n```\n\nOrder a query by a field\n\n#### func (OrderBy) Sort\n\n```go\nfunc (o OrderBy) Sort([]query.Entry)\n```\nsatisfy datastore.Order interface, this is a no-op b/c sql sorting will happen\nat query-time TODO - In the future this should be generalized to facilitate\nsupplying sql_datastore.OrderBy orders to other datastores, providing parity\n\n#### func (OrderBy) String\n\n```go\nfunc (o OrderBy) String() string\n```\nString value, used to inject the field name istself as a SQL query param\n\n#### type OrderByDesc\n\n```go\ntype OrderByDesc string\n```\n\nOrder a query by a field, descending\n\n#### func (OrderByDesc) Sort\n\n```go\nfunc (o OrderByDesc) Sort([]query.Entry)\n```\nsatisfy datastore.Order interface, this is a no-op b/c sql sorting will happen\nat query-time TODO - In the future this should be generalized to facilitate\nsupplying sql_datastore.OrderBy orders to other datastores, providing parity\n\n#### func (OrderByDesc) String\n\n```go\nfunc (o OrderByDesc) String() string\n```\nString value, used to inject the field name istself as a SQL query param\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdatatogether%2Fsql_datastore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdatatogether%2Fsql_datastore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdatatogether%2Fsql_datastore/lists"}