diff --git a/client.go b/client.go index 96e725876..058d6d836 100644 --- a/client.go +++ b/client.go @@ -389,11 +389,13 @@ func (c *Client) importNode(ctx context.Context, node *Node, buf []byte) error { } // ExportCSV bulk exports data for a single slice from a host to CSV format. -func (c *Client) ExportCSV(ctx context.Context, index, frame string, slice uint64, w io.Writer) error { +func (c *Client) ExportCSV(ctx context.Context, index, frame, view string, slice uint64, w io.Writer) error { if index == "" { return ErrIndexRequired } else if frame == "" { return ErrFrameRequired + } else if !(view == ViewStandard || view == ViewInverse) { + return ErrInvalidView } // Retrieve a list of nodes that own the slice. @@ -407,7 +409,7 @@ func (c *Client) ExportCSV(ctx context.Context, index, frame string, slice uint6 for _, i := range rand.Perm(len(nodes)) { node := nodes[i] - if err := c.exportNodeCSV(ctx, node, index, frame, slice, w); err != nil { + if err := c.exportNodeCSV(ctx, node, index, frame, view, slice, w); err != nil { e = fmt.Errorf("export node: host=%s, err=%s", node.Host, err) continue } else { @@ -419,7 +421,7 @@ func (c *Client) ExportCSV(ctx context.Context, index, frame string, slice uint6 } // exportNode copies a CSV export from a node to w. -func (c *Client) exportNodeCSV(ctx context.Context, node *Node, index, frame string, slice uint64, w io.Writer) error { +func (c *Client) exportNodeCSV(ctx context.Context, node *Node, index, frame, view string, slice uint64, w io.Writer) error { // Create URL. u := url.URL{ Scheme: "http", @@ -428,6 +430,7 @@ func (c *Client) exportNodeCSV(ctx context.Context, node *Node, index, frame str RawQuery: url.Values{ "index": {index}, "frame": {frame}, + "view": {view}, "slice": {strconv.FormatUint(slice, 10)}, }.Encode(), } diff --git a/cmd/export.go b/cmd/export.go index 310e3f05c..e55f84e59 100644 --- a/cmd/export.go +++ b/cmd/export.go @@ -51,8 +51,9 @@ The file does not contain any headers. flags := exportCmd.Flags() flags.StringVarP(&Exporter.Host, "host", "", "localhost:10101", "host:port of Pilosa.") - flags.StringVarP(&Exporter.Index, "index", "i", "", "Pilosa index to export into.") - flags.StringVarP(&Exporter.Frame, "frame", "f", "", "Frame to export into.") + flags.StringVarP(&Exporter.Index, "index", "i", "", "Pilosa index to export") + flags.StringVarP(&Exporter.Frame, "frame", "f", "", "Frame to export") + flags.StringVarP(&Exporter.View, "view", "v", "standard", "View to export - default standard") flags.StringVarP(&Exporter.Path, "output-file", "o", "", "File to write export to - default stdout") return exportCmd diff --git a/cmd/export_test.go b/cmd/export_test.go index 2b30116c6..2d01cf4d6 100644 --- a/cmd/export_test.go +++ b/cmd/export_test.go @@ -44,6 +44,7 @@ frame = "f1" v.Check(cmd.Exporter.Host, "localhost:12345") v.Check(cmd.Exporter.Index, "myindex") v.Check(cmd.Exporter.Frame, "f1") + v.Check(cmd.Exporter.View, "standard") v.Check(cmd.Exporter.Path, "/somefile") return v.Error() }, @@ -51,3 +52,10 @@ frame = "f1" } executeDry(t, tests) } + +func TestExportInvalidView(t *testing.T) { + output, err := ExecNewRootCommand(t, "export", "-i", "foo", "-f", "bar", "-v", "test") + if !strings.Contains(err.Error(), "invalid view") { + t.Fatalf("Command 'export' with invalid view should error but: err: '%v', output: '%v'", err, output) + } +} diff --git a/ctl/export.go b/ctl/export.go index 8f67b7896..7da310623 100644 --- a/ctl/export.go +++ b/ctl/export.go @@ -31,7 +31,7 @@ type ExportCommand struct { // Name of the index & frame to export from. Index string Frame string - + View string // Filename to export to. Path string @@ -55,6 +55,8 @@ func (cmd *ExportCommand) Run(ctx context.Context) error { return pilosa.ErrIndexRequired } else if cmd.Frame == "" { return pilosa.ErrFrameRequired + } else if !(cmd.View == pilosa.ViewStandard || cmd.View == pilosa.ViewInverse) { + return pilosa.ErrInvalidView } // Use output file, if specified. @@ -85,7 +87,7 @@ func (cmd *ExportCommand) Run(ctx context.Context) error { // Export each slice. for slice := uint64(0); slice <= maxSlices[cmd.Index]; slice++ { logger.Printf("exporting slice: %d", slice) - if err := client.ExportCSV(ctx, cmd.Index, cmd.Frame, slice, w); err != nil { + if err := client.ExportCSV(ctx, cmd.Index, cmd.Frame, cmd.View, slice, w); err != nil { return err } }