Add Download() function, for retrieving a remote database file

This commit is contained in:
Justin Clift
2020-08-05 00:10:10 +10:00
parent 92052c278f
commit fdc8abb28c
4 changed files with 82 additions and 16 deletions

View File

@@ -12,13 +12,13 @@ A Go library for accessing and using SQLite databases stored remotely on DBHub.i
* List the columns present in a table or view, along with their details
* List the branches of a database
* Generate diffs between two databases, or database revisions
* Download a complete database
### Still to do
* Tests for each function
* Retrieve index details for a database
* Return the list of available databases
* Download a complete database
* Upload a complete database
* Retrieve database commit history details (size, branch, commit list, whatever else is useful)
* Investigate what would be needed for this to work through the Go SQL API
@@ -134,5 +134,6 @@ ORDER BY table1.id;
* [Retrieve column details](https://github.com/sqlitebrowser/go-dbhub/blob/master/examples/column_details/main.go) - Retrieve the details of columns in a table
* [List branches](https://github.com/sqlitebrowser/go-dbhub/blob/master/examples/list_branches/main.go) - List all branches of a database
* [Generate diff between two revisions](https://github.com/sqlitebrowser/go-dbhub/blob/master/examples/diff_commits/main.go) - Figure out the differences between two databases or two versions of one database
* [Download database](https://github.com/sqlitebrowser/go-dbhub/blob/master/examples/download_database/main.go) - Download the complete database file
Please try it out, submits PRs to extend or fix things, and report any weirdness or bugs you encounter. :smile:

View File

@@ -5,6 +5,7 @@ package dbhub
import (
"encoding/base64"
"fmt"
"io"
"net/url"
com "github.com/sqlitebrowser/dbhub.io/common"
@@ -45,7 +46,7 @@ func (c Connection) Branches(dbowner, dbname string) (branches map[string]com.Br
// Fetch the list of branches and the default branch
var response com.BranchListResponseContainer
queryUrl := c.Server + "/v1/branches"
err = sendRequest(queryUrl, data, &response)
err = sendRequestJSON(queryUrl, data, &response)
// Extract information for return values
branches = response.Entries
@@ -61,7 +62,7 @@ func (c Connection) Columns(dbOwner, dbName string, ident Identifier, table stri
// Fetch the list of columns
queryUrl := c.Server + "/v1/columns"
err = sendRequest(queryUrl, data, &columns)
err = sendRequestJSON(queryUrl, data, &columns)
return
}
@@ -109,7 +110,21 @@ func (c Connection) Diff(dbOwnerA, dbNameA string, identA Identifier, dbOwnerB,
// Fetch the diffs
queryUrl := c.Server + "/v1/diff"
err = sendRequest(queryUrl, data, &diffs)
err = sendRequestJSON(queryUrl, data, &diffs)
return
}
// Download returns the database file
func (c Connection) Download(dbOwner, dbName string, ident Identifier) (db io.ReadCloser, err error) {
// Prepare the API parameters
data := c.PrepareVals(dbOwner, dbName, ident)
// Fetch the database file
queryUrl := c.Server + "/v1/download"
db, err = sendRequest(queryUrl, data)
if err != nil {
return
}
return
}
@@ -120,7 +135,7 @@ func (c Connection) Indexes(dbOwner, dbName string, ident Identifier) (idx map[s
// Fetch the list of indexes
queryUrl := c.Server + "/v1/indexes"
err = sendRequest(queryUrl, data, &idx)
err = sendRequestJSON(queryUrl, data, &idx)
return
}
@@ -158,7 +173,7 @@ func (c Connection) Query(dbOwner, dbName string, ident Identifier, blobBase64 b
// Run the query on the remote database
var returnedData []com.DataRow
queryUrl := c.Server + "/v1/query"
err = sendRequest(queryUrl, data, &returnedData)
err = sendRequestJSON(queryUrl, data, &returnedData)
if err != nil {
return
}
@@ -204,7 +219,7 @@ func (c Connection) Tables(dbOwner, dbName string, ident Identifier) (tbl []stri
// Fetch the list of tables
queryUrl := c.Server + "/v1/tables"
err = sendRequest(queryUrl, data, &tbl)
err = sendRequestJSON(queryUrl, data, &tbl)
return
}
@@ -215,6 +230,6 @@ func (c Connection) Views(dbOwner, dbName string, ident Identifier) (views []str
// Fetch the list of views
queryUrl := c.Server + "/v1/views"
err = sendRequest(queryUrl, data, &views)
err = sendRequestJSON(queryUrl, data, &views)
return
}

View File

@@ -0,0 +1,35 @@
package main
import (
"fmt"
"io/ioutil"
"log"
"github.com/sqlitebrowser/go-dbhub"
)
func main() {
// Create a new DBHub.io API object
db, err := dbhub.New("YOUR_API_KEY_HERE")
if err != nil {
log.Fatal(err)
}
// Retrieve the remote database file
dbName := "Join Testing.sqlite"
dbStream, err := db.Download("justinclift", dbName, dbhub.Identifier{})
if err != nil {
log.Fatal(err)
}
// Save the database file in the current directory
buf, err := ioutil.ReadAll(dbStream)
if err != nil {
log.Fatal(err)
}
err = ioutil.WriteFile(dbName, buf, 0644)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Saved database file as '%s'\n", dbName)
}

31
http.go
View File

@@ -3,14 +3,32 @@ package dbhub
import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strings"
)
// sendRequest sends the query to the server. It exists because http.PostForm() doesn't seem to have a way
// to change header values.
func sendRequest(queryUrl string, data url.Values, returnStructure interface{}) (err error) {
// sendRequestJSON sends a request to DBHub.io, formatting the returned result as JSON
func sendRequestJSON(queryUrl string, data url.Values, returnStructure interface{}) (err error) {
// Send the request
var body io.ReadCloser
body, err = sendRequest(queryUrl, data)
if err != nil {
return
}
// Unmarshall the JSON response into the structure provided by the caller
err = json.NewDecoder(body).Decode(returnStructure)
if err != nil {
return
}
return
}
// sendRequest sends a request to DBHub.io. It exists because http.PostForm() doesn't seem to have a way of changing
// header values.
func sendRequest(queryUrl string, data url.Values) (body io.ReadCloser, err error) {
var req *http.Request
var resp *http.Response
var client http.Client
@@ -35,10 +53,7 @@ func sendRequest(queryUrl string, data url.Values, returnStructure interface{})
return
}
// Unmarshall the JSON response into the structure provided by the caller
err = json.NewDecoder(resp.Body).Decode(returnStructure)
if err != nil {
return
}
// Return the response body
body = resp.Body
return
}