Merge pull request #270 from sosedoff/data-export

Database export
This commit is contained in:
Dan Sosedoff 2017-09-19 00:41:04 -05:00 committed by GitHub
commit f5f595ac02
6 changed files with 106 additions and 8 deletions

View File

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
neturl "net/url"
"strings"
"time"
"github.com/gin-gonic/gin"
@ -398,3 +399,32 @@ func GetInfo(c *gin.Context) {
c.JSON(200, info)
}
// Export database or table data
func DataExport(c *gin.Context) {
db := DB(c)
info, err := db.Info()
if err != nil {
c.JSON(400, Error{err.Error()})
return
}
dump := client.Dump{
Table: strings.TrimSpace(c.Request.FormValue("table")),
}
formattedInfo := info.Format()[0]
filename := formattedInfo["current_database"].(string)
if dump.Table != "" {
filename = filename + "_" + dump.Table
}
attachment := fmt.Sprintf(`attachment; filename="%s.sql.gz"`, filename)
c.Header("Content-Disposition", attachment)
err = dump.Export(db.ConnectionString, c.Writer)
if err != nil {
c.JSON(400, Error{err.Error()})
}
}

View File

@ -47,5 +47,6 @@ func SetupRoutes(router *gin.Engine) {
api.POST("/explain", ExplainQuery)
api.GET("/history", GetHistory)
api.GET("/bookmarks", GetBookmarks)
api.GET("/export", DataExport)
}
}

37
pkg/client/dump.go Normal file
View File

@ -0,0 +1,37 @@
package client
import (
"bytes"
"fmt"
"io"
"os/exec"
)
type Dump struct {
Table string
}
func (d *Dump) Export(url string, writer io.Writer) error {
errOutput := bytes.NewBuffer(nil)
opts := []string{
"--no-owner", // skip restoration of object ownership in plain-text format
"--clean", // clean (drop) database objects before recreating
"--compress", "6", // compression level for compressed formats
}
if d.Table != "" {
opts = append(opts, []string{"--table", d.Table}...)
}
opts = append(opts, url)
cmd := exec.Command("pg_dump", opts...)
cmd.Stdout = writer
cmd.Stderr = errOutput
if err := cmd.Run(); err != nil {
return fmt.Errorf("error: %s. output: %s", err.Error(), errOutput.Bytes())
}
return nil
}

File diff suppressed because one or more lines are too long

View File

@ -239,6 +239,8 @@
<li><a href="#" data-action="export" data-format="csv">Export to CSV</a></li>
<li><a href="#" data-action="export" data-format="xml">Export to XML</a></li>
<li class="divider"></li>
<li><a href="#" data-action="dump">Export SQL dump</a></li>
<li class="divider"></li>
<li><a href="#" data-action="truncate">Truncate Table</a></li>
<li><a href="#" data-action="delete">Delete Table</a></li>
</ul>
@ -246,6 +248,11 @@
<div id="databases_context_menu">
<ul class="dropdown-menu" role="menu"></ul>
</div>
<div id="current_database_context_menu">
<ul class="dropdown-menu" role="menu">
<li><a href="#" data-action="export">Export SQL dump</a></li>
</ul>
</div>
<div id="results_header_menu">
<ul class="dropdown-menu" role="menu">
<li><a href="#" data-action="unique_values" data-counts="false">Unique Values</a></li>

View File

@ -219,6 +219,11 @@ function performTableAction(table, action, el) {
var win = window.open(url, "_blank");
win.focus();
break;
case "dump":
var url = window.location.href.split("#")[0] + "api/export?table=" + table + "&_session_id=" + getSessionId();
var win = window.open(url, "_blank");
win.focus();
break;
}
}
@ -809,8 +814,26 @@ function bindTableHeaderMenu() {
});
}
function bindCurrentDatabaseMenu() {
$("#current_database").contextmenu({
target: "#current_database_context_menu",
onItem: function(context, e) {
var menuItem = $(e.target);
switch(menuItem.data("action")) {
case "export":
var url = window.location.href.split("#")[0] + "api/export?_session_id=" + getSessionId();
var win = window.open(url, "_blank");
win.focus();
break;
}
}
});
}
function bindContextMenus() {
bindTableHeaderMenu();
bindCurrentDatabaseMenu();
$(".schema-group ul").each(function(id, el) {
$(el).contextmenu({
@ -825,7 +848,7 @@ function bindContextMenus() {
});
});
$("#current_database").contextmenu({
$(".tables-list .title").contextmenu({
target: "#databases_context_menu",
onItem: function(context, e) {
var name = $(e.target).text();
@ -1037,7 +1060,7 @@ $(document).ready(function() {
resp.forEach(function(name) {
$("<li><a href='#'>" + name + "</a></li>").appendTo("#databases_context_menu > ul");
});
$("#current_database").triggerHandler("contextmenu");
$(".tables-list .title").triggerHandler("contextmenu");
});
});